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

时间:2018-01-22 09:55:40

标签: java generics netty

在netty中定义监听器如下: 例如,在类io.netty.util.concurrent.CompleteFuture:

@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;
}

据我所知:Futrue&lt;?超级V&gt;表示超级V的Class集合。因此,它是继承树中的集合,因为我们有Future&lt; V&gt;。和未来&lt;对象&gt;至少。假设集合的名称是C。

所以这就是问题,是什么?当C是集合时,扩展C表示意味着什么?

希望有人能够启发我!

1 个答案:

答案 0 :(得分:4)

我假设您的声明来自Netty的Promise课程。我认为我的答案应该无论如何都应该有效,因为你的问题似乎是关于协方差和逆变的,而不是明确的关于Netty的API。

public interface Promise<V> extends Future<V> {

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

此处仿制药的目的是使API对其用户更具有可塑性。

假设您有三个不同类型参数的三个不同GenericFutureListener个对象:IntegerNumberObject

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

请注意,IntegerNumber的子类型,而Object的子类型是Promise的子类型。

现在假设我们的Integer类型为Promise<Integer> p = somePromise; ,有点如下

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

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

GenericFutureListener

基本上,Integer可能会对p.addListener(fl1); p.addListener(fl2); p.addListener(fl3); 或其任何超类型的期货进行操作。

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

Integer

请注意,我没有被迫为显式类型p的未来提供监听器。如果您认为这完全有意义,因为如果我的承诺Integer产生Integer,而Number Number,那么知道如何处理Integer未来的监听器也应该能够处理Object的未来。如果我的监听器知道如何处理Integer的未来,并且Object Object,那么让我们应该没有问题聆听未来Integer来处理Future<? super V>的未来,对吧?

嗯,这正是Future在上面的声明中的含义。这是一种被称为逆变的概念。

现在,事实是,在Netty中Future是一个接口,许多不同的类可以实现GenericFutureListener。我们希望我们的Future能够使用Future的任何子类型,而不只是Promise本身,对吗?

例如,Future实际上是GenericFutureListener<Promise<Integer>> fl4 = System.out::println; GenericFutureListener<Promise<Number>> fl5 = System.out::println; GenericFutureListener<Promise<Object>> fl6 = System.out::println; 的子类型:

GenericFutureListener

正如您所看到的,Promise在这里接受<? extends Future>作为类型参数。这要归功于GenericFutureListener的宣言。没有它,Future只接受此处的p.addListener(fl4); p.addListener(fl5); p.addListener(fl6); 类型,这会使此API灵活性降低,对吧?

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

现在我们可以使我们的原始承诺还添加第二组侦听器:

public function IsAdmin()
{
    return Controller::curr() instanceof LeftAndMain ? true : false;
}

你有它。正确使用协方差和逆变,这是一个更加灵活的API。