代码之家  ›  专栏  ›  技术社区  ›  Myk Willis

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

  •  2
  • Myk Willis  · 技术社区  · 6 年前

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

    现在我想更改我的方法,使其不接受 列表 ,而不是 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 ,这里的问题似乎不是子类和基类集合之间的错误假设转换。相反,它似乎更多地和所使用的可观察的具体类型有关。

        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拆包和浇筑:

    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!
    }
    

    当然有更干净的方法来完成我想做的事情吗?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Jorn Vernee    6 年前

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

    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> A. 不同的 类型大于 T .但是自从 generics are invariant 您不能分配 可观察(<U> 可观察(<T> 即使 U 可转让给 T

    要让它工作,你需要 Observable<? extends T> 作为参数。如果您随后替换 T 对于 列出(<);?扩展基类(&T)&燃气轮机; 您再次获得:

    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); 
    
        2
  •  0
  •   user3237736    6 年前

    看来这可能是一个解决办法:

    static <T extends BaseClass> void observableListMethod(Observable<List<T>> listObservable)
    

    也许我误解了这个问题,但至少这个问题是为我准备的。