将具有指定泛型列表类型的 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
,而是接受发出 List
的 Observable
。因此签名变为:
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>
,其中 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);
我可以编写一个接受 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
,而是接受发出 List
的 Observable
。因此签名变为:
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>
,其中 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);