【问题标题】:Unexpected type inference with RxJava使用 RxJava 进行意外的类型推断
【发布时间】:2018-11-22 21:35:05
【问题描述】:

我有一个普通的 Transformer,它只是使用给定的谓词过滤列表:

public class ListFilter<T> implements Observable.Transformer<List<T>, List<T>> {
    private final Predicate<T> predicate;

    private ListFilter(Predicate<T> predicate) {
        this.predicate = predicate;
    }

    public static <T> Observable.Transformer<List<T>, List<T>> create(Predicate<T> predicate) {
        return new ListFilter<>(predicate);
    }

    @Override
    public Observable<List<T>> call(Observable<List<T>> listObservable) {
        return listObservable
                .flatMap(list -> Observable.from(list)
                        .filter(predicate::test)
                        .toList());
    }
}

现在我可以过滤具有最少样板的项目列表,如下所示:

repository.observeItems() // returns Observable<List<SomeItem>>
        .compose(ListFilter.create(item -> /* some filter logic */)

但有一点我无法解释:

List<? extends Dummy> list = SomeDummyFactory.create();
BehaviorSubject<List<? extends Dummy>> subject = BehaviorSubject.create(list);

// #1 -> ok
BehaviorSubject.create(list)
    .compose(ListFilter.create(item -> /* `item` is `Dummy` */)
    ...

// #2 -> error
subject
    .compose(ListFilter.create(item -> /* `item` is `Object` */)) 
    ...

// #3 -> ok
subject
    .map(any -> any) // do nothing
    .compose(ListFilter.create(item -> /* `item` is `Dummy` */)) 
    ...

我在#2 和#3 之间看到的唯一区别是Transformer&lt;T, R&gt; 的预期通配符:

  • _#2:Transformer&lt;? super List&lt;? extends Dummy&gt;, ? extends R&gt;
  • _#3:Transformer&lt;? super List&lt;capture of ? extends Dummy&gt;, ? extends List&lt;capture of ? extends Dummy&gt;

所以有几个问题:

  1. 为什么Object 是第二种情况下的item 类型(而不是Dummy)?
  2. 为什么 Java 在第二种情况下不能推断出 Transformer 的返回类型?
  3. map 运营商如何提供帮助?
  4. 为什么第一种情况可以正常工作?

【问题讨论】:

    标签: java generics collections rx-java rx-java2


    【解决方案1】:

    这是因为编译器无法重新捕获通配符类型。

    在您的第一种情况下,您可以尝试添加显式泛型。 &lt;Dummy&gt;&lt;Object&gt; 都会导致错误。事实geneirc 类型是(captrue#1 ?) extends Dummy,由create 的通用返回值推断。

    在第二种情况下,您的 subject 泛型类型是 List&lt;? extends Dummy&gt;compose 必须接受Transformer&lt;? super List&lt;? extends Dummy&gt;,? extends R&gt;&gt;,所以create 泛型必须是? extends Dummy(与案例1 相同)。但在当前编译上下文(当前语句)中,未捕获通配符类型。编译器无法推断泛型类型,它只是使用Object,所以会发生错误。

    在第三种情况下,map 捕获通配符类型。您可以尝试任何具有通用 Observable&lt;R&gt; 返回类型的方法,它们都可以工作。如.flatMap(d -&gt; Observable.just(d))

    但请注意,您的案例 3 只是一种解决方法。推荐的解决方案是让您的ListFilter 的泛型更加灵活。

    您应该将其定义为ObservableTransformer&lt;List&lt;? extends T&gt;, List&lt;? extends T&gt;&gt;

    class ListFilter<T> implements ObservableTransformer<List<? extends T>, List<? extends T>> {
    
      public static <T> ListFilter<T> create(Predicate<T> predicate) {
        return new ListFilter<>(predicate);
      }
    
      private final Predicate<T> predicate;
    
      private ListFilter(Predicate<T> predicate) {
        this.predicate = predicate;
      }
    
      @Override
      public ObservableSource<List<? extends T>> apply(Observable<List<? extends T>> upstream) {
        return upstream
            .flatMapSingle(list -> Observable.fromIterable(list)
                .filter(predicate::test)
                .toList());
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-03
      • 2012-11-13
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多