在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表示意味着什么?
希望有人能够启发我!
答案 0 :(得分:4)
我假设您的声明来自Netty的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;
请注意,Integer
是Number
的子类型,而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。