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

Passing Observable with specified generic List type as method argument

我可以编写一个接受 List 的方法,其中的元素扩展给定的基 class,如下所示:

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,而是接受发出 ListObservable。因此签名变为:

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 的一般问题不同,这里的问题似乎不是 subclass 和 baseclass 集合之间的错误假设转换。相反,它似乎与所使用的 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 <T extends BaseClass> void observableListMethod(Observable<List<T>> listObservable)

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

正如另一个答案所示,您可以使用类型变量来解决这个问题。但是要解释发生了什么;

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);