java - 将具有指定泛型列表类型的 Observable 作为方法参数传递

标签 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发出 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>哪里TList<? extends BaseClass>> .

现在,您尝试传递 Observable<List<BaseClass>>例如,即 Observable<U>哪里UList<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/

相关文章:

Kotlin - 如何创建 RxJava flatmap() 的别名函数?

java - 如何在 Maven 和 IntelliJ 之间共享 Clover 覆盖率数据

java - java中的枚举错误

c# - 为什么在测试受约束的泛型类型时直接转换失败但 "as"运算符成功?

Scala 转换为泛型类型(用于泛型数值函数)

wpf - 我如何使用 {x :Type generic:List<sys:String>} in WPF xaml?

java - 如何将 Angular-Cli 前端与 Spring-boot 后端相结合

java.lang.NoSuchMethodError : javax. ws.rs.core.Application.getProperties()Ljava/util/Map;

android - RxAndroid 一个接一个地调用网络调用

rx-java - 接收超时操作符