代码之家  ›  专栏  ›  技术社区  ›  John Milton

对GenericFutureListener中使用的Netty泛型类型感到困惑吗?

  •  1
  • John Milton  · 技术社区  · 7 年前

    在netty中,定义侦听器如下: 例如,在io类中。内蒂。util。同时发生的完成未来:

    @Override
    public Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) {
        if (listener == null) {
            throw new NullPointerException("listener");
        }
        DefaultPromise.notifyListener(executor(), this, listener);
        return this;
    }
    

    据我所知,未来<?超级V>表示超V类的集合。因此它是继承树中的集合,因为我们有未来<V>和未来<对象(>);至少假设集合的名称为C。

    那么问题来了,是什么?扩展C意味着C是一个集合?

    希望有人能启发我!

    1 回复  |  直到 3 年前
        1
  •  5
  •   Edwin Dalorzo    7 年前

    我想你上面的声明来自内蒂 Promise 班我认为我的答案应该是可行的,因为你的问题似乎更多的是关于协方差和逆变,而不是关于Netty的API。

    public interface Promise<V> extends Future<V> {
    
       Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
       //...
    }
    

    这里泛型的目的是使API对其用户更具可塑性。

    假设您有三个不同的 GenericFutureListener 具有三个不同类型参数的对象: Integer , Number Object .

    GenericFutureListener<Future<Integer>> fl1 = System.out::println;
    GenericFutureListener<Future<Number>> fl2 = System.out::println;
    GenericFutureListener<Future<Object>> fl3 = System.out::println;
    

    请注意 整数 是的子类型 数字 这又是 对象 .

    假设现在我们有一个 Promise 的类型 整数 ,大致如下

    Promise<Integer> p = somePromise;
    

    编译器会将我们的方法声明解释为

    Promise<Integer> addListener(GenericFutureListener<? extendsFuture<? super Integer>> listener);
    

    基本上就是说 通用未来监听器 可能操作类型的期货 整数 , 或者它的任何超级类型 .

    这显然使API更加灵活,例如,我可以添加我之前定义的任何监听器,以便在我的整数承诺得到解决时得到通知:

    p.addListener(fl1);
    p.addListener(fl2);
    p.addListener(fl3);
    

    请注意,我没有被迫为显式类型的未来提供侦听器 整数 . 如果你仔细想想,这完全有道理,因为如果我的承诺 p 生成 整数 ,和 整数 是一个 数字 ,然后是一个知道如何处理 数字 应该能够处理 整数 也如果我的听众知道如何处理 对象 ,和 整数 是一个 对象 ,那么,让一个倾听者 对象 处理未来的 整数 正当

    嗯,这就是 Future<? super V> 指上述声明中的。这一概念被称为逆变。

    事实是在Netty Future 是一个接口,可以实现许多不同的类 将来 . 我们希望 通用未来监听器 能够使用的任何子类型 将来 而且不仅仅是 将来 本身,对吧?。

    例如,a 许诺 实际上是 将来 :

    GenericFutureListener<Promise<Integer>> fl4 = System.out::println;
    GenericFutureListener<Promise<Number>> fl5 = System.out::println;
    GenericFutureListener<Promise<Object>> fl6 = System.out::println;
    

    正如你所见, 通用未来监听器 接受 许诺 作为此处的类型参数。这要感谢 <? extends Future> . 没有它, 通用未来监听器 只接受 将来 在此处键入,这将使此API的灵活性大大降低,对吗?。

    这个概念被称为协方差,它再次被用来使API对其用户更加灵活。

    现在,我们可以做出最初的承诺,同时添加以下第二组侦听器:

    p.addListener(fl4);
    p.addListener(fl5);
    p.addListener(fl6);
    

    就在这里。由于协方差和逆变的正确使用,API更加灵活。