我可以编写一个接受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
的{{1}}。签名因此变为:
List
不幸的是,尝试调用此新方法会导致形式的参数不匹配错误:
static void observableListMethod(Observable<List<? extends BaseClass>> listObservable) { }
与dealing with generic collections in Java的一般问题不同,这里的问题似乎不是在子类和基类集合之间进行错误的假设。相反,它似乎更多地与正在使用的Observable的特定类型有关。
Observable<List<BaseClass>> cannot be converted to Observable<List<? extends BaseClass>>
我到目前为止提出的最佳解决方案是更改方法签名以明确指定 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
解包并使用Rx进行投射:
List
当然,有一种更清洁的方法来完成我想要做的事情?
答案 0 :(得分:3)
正如另一个答案所示,您可以使用类型变量来解决此问题。但要解释发生了什么;
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>
,与不同的类型{ {1}}。但是,由于generics are invariant您无法将T
分配给Observable<U>
。即使Observable<T>
可分配给U
。
要使其有效,您需要T
作为参数。如果您再次将Observable<? extends T>
替换为T
,则会获得:
List<? extends BaseClass>>
如果你将参数类型改为编译:
Observable<? extends List<? extends BaseClass>>
答案 1 :(得分:0)
似乎这可能是一种解决方法:
static <T extends BaseClass> void observableListMethod(Observable<List<T>> listObservable)
也许我误解了这个问题,但至少那个问题正在为我编译。