Joh*_*ton 1 java generics netty
在 netty 中定义监听器如下:\n例如在 io.netty.util.concurrent.CompleteFuture 类中:
\n@Override\npublic Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) {\n if (listener == null) {\n throw new NullPointerException("listener");\n }\n DefaultPromise.notifyListener(executor(), this, listener);\n return this;\n}\n
Run Code Online (Sandbox Code Playgroud)\n据我所知\xef\xbc\x9aFuture<? super V> 表示取代 V 的 Class 的集合。所以它是继承树中的集合,因为我们至少有 Future<V> 和 Future<Object> 。假设集合的名称是 C。
\n那么问题来了,什么是?扩展 C 意味着 C 是一个集合?
\n希望有人能启发我!
\n我假设您上面的声明来自 Netty 的Promise类。我认为不管怎样,我的答案应该有效,因为你的问题似乎更多地是关于协变和逆变,而不是明确地关于 Netty 的 API。
public interface Promise<V> extends Future<V> {
Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
//...
}
Run Code Online (Sandbox Code Playgroud)
这里泛型的目的是让 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;
Run Code Online (Sandbox Code Playgroud)
请注意,Integer
是 的子类型,Number
而 又是 的子类型Object
。
假设现在我们有一个Promise
of 类型Integer
,如下所示
Promise<Integer> p = somePromise;
Run Code Online (Sandbox Code Playgroud)
我们的方法声明将被编译器解释为
Promise<Integer> addListener(GenericFutureListener<? extendsFuture<? super Integer>> listener);
Run Code Online (Sandbox Code Playgroud)
这基本上是说,GenericFutureListener
可能对类型或其任何超级类型的期货Integer
进行操作。
这显然使 API 更加灵活,例如,我可以添加之前定义的任何侦听器,以便在解决我的 Integer 承诺时收到通知:
p.addListener(fl1);
p.addListener(fl2);
p.addListener(fl3);
Run Code Online (Sandbox Code Playgroud)
请注意,我没有被迫为显式类型的 future 提供侦听器Integer
。如果你仔细想想,这完全是有道理的,因为如果我的承诺p
产生一个Integer
,并且一个Integer
是一个 Number
,那么知道如何处理 的 未来 的听众Number
也应该能够处理 的 未来Integer
。如果我有知道如何处理 的未来的侦听器Object
,并且 anInteger
是 an ,那么让 的 未来的侦听器处理 的 未来Object
应该没有问题Object
Integer
,对吧?
嗯,这正是Future<? super V>
上面声明中的含义。这是称为逆变的概念。
现在,事实是 Netty 中Future
是一个接口,许多不同的类可以实现Future
. 我们希望我们GenericFutureListener
能够使用任何子类型Future
而不仅仅是Future
它本身,对吧?
例如, aPromise
实际上是 的子类型Future
:
GenericFutureListener<Promise<Integer>> fl4 = System.out::println;
GenericFutureListener<Promise<Number>> fl5 = System.out::println;
GenericFutureListener<Promise<Object>> fl6 = System.out::println;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这里GenericFutureListener
接受Promise
作为类型参数。这要归功于 的声明<? extends Future>
。如果没有它,GenericFutureListener
就只能接受Future
这里的类型,这会使这个 API 的灵活性大大降低,对吧?
这个概念称为协方差,它再次用于使 API 对于用户来说更加灵活。
现在我们可以让我们最初的承诺也添加第二组监听器:
p.addListener(fl4);
p.addListener(fl5);
p.addListener(fl6);
Run Code Online (Sandbox Code Playgroud)
现在你就得到了它。由于协变和逆变的正确使用,API 更加灵活。
归档时间: |
|
查看次数: |
496 次 |
最近记录: |