我可以编写一个接受 List
的方法,其元素扩展给定的基类,如下所示:
class BaseClass { }
class SubClass extends BaseClass { }
static void listMethod(List<? extends BaseClass> list) { }
调用此方法非常简单,并且按预期工作:
List<BaseClass> b = Collections.empty();
List<SubClass> s = Collections.empty();
listMethod(b); // ok
listMethod(s); // ok
现在我想更改我的方法,使其不接受 List
,而是 Observable
发出 List
。签名因此更改为:
static void observableListMethod(Observable<List<? extends BaseClass>> listObservable) { }
不幸的是,尝试调用这个新方法会导致以下形式的参数不匹配错误:
Observable<List<BaseClass>> cannot be converted to Observable<List<? extends BaseClass>>
与dealing with generic collections in Java的一般问题不同,这里的问题似乎不是子类和基类集合之间的错误假设转换。相反,它似乎与所使用的 Observable 的特定类型有更多关系。
Observable<List<BaseClass>> b = Observable.just(Collections.emptyList());
Observable<List<SubClass>> s = Observable.just(Collections.emptyList());
observableListMethod(b); // argument mismatch / incompatible types
observableListMethod(s); // argument mismatch / incompatible types
// I can map the List to a read-only variant...
observableListMethod(b.map(Collections::unmodifiableList)); // ok (for readonly)
observableListMethod(s.map(Collections::unmodifiableList)); // ok (for readonly)
到目前为止,我想出的最佳解决方案是更改方法签名以指定 BaseClass
具体来说(不是 ? extends BaseClass
),然后做一些丑陋的 List
使用 Rx 解包和转换:
static void observableListMethod2(Observable<List<BaseClass>> listObservable) { }
public static void callObservableListMethod2() {
Observable<List<BaseClass>> b = Observable.just(Collections.emptyList());
Observable<List<SubClass>> s = Observable.just(Collections.emptyList());
observableListMethod2(b); // ok
observableListMethod2(s.flatMapIterable(it -> it).cast(BaseClass.class).toList()); // ok, but yuck!
}
肯定有一种更干净的方法来完成我想做的事情吗?
最佳答案
正如另一个答案所示,您可以通过使用类型变量来解决这个问题。但要解释发生了什么;
static void observableListMethod(Observable<List<? extends BaseClass>> listObservable) { }
需要 Observable<List<? extends BaseClass>>
作为参数。换句话说,它需要 Observable<T>
哪里T
是 List<? extends BaseClass>>
.
现在,您尝试传递 Observable<List<BaseClass>>
例如,即 Observable<U>
哪里U
是 List<BaseClass>
,与 T
不同的类型。但自从 generics are invariant您不能分配 Observable<U>
到Observable<T>
。即使U
可分配给T
.
要使其正常工作,您需要 Observable<? extends T>
作为参数。如果您替换 T
对于 List<? extends BaseClass>>
你再次得到:
Observable<? extends List<? extends BaseClass>>
如果您指定参数类型,则应编译:
Observable<List<BaseClass>> b = Observable.just(Collections.emptyList());
Observable<List<SubClass>> s = Observable.just(Collections.emptyList());
observableListMethod(b);
observableListMethod(s);
关于java - 将具有指定泛型列表类型的 Observable 作为方法参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49762105/