使用指定的通用List类型传递Observable作为方法参数

时间:2018-04-10 20:07:28

标签: java generics rx-java generic-programming

我可以编写一个接受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

当然,有一种更清洁的方法来完成我想要做的事情?

2 个答案:

答案 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)

也许我误解了这个问题,但至少那个问题正在为我编译。