我在维护的代码中遇到了此类:
new GenericFutureListener<Future<? super Void>>() {...}
我很难理解这意味着什么。包含类型为Future
或其超类-Void
的{{1}}。那么,为什么不只写Object
呢?
答案 0 :(得分:13)
没有其他人指出:这是Netty,如果您查看https://netty.io/4.0/api/io/netty/util/concurrent/class-use/Future.html,则会在库中看到一些采用这种类型的方法,例如ChannelPromise.addListener(GenericFutureListener<? extends Future<? super java.lang.Void>> listener)
。由于一般情况,这些方法具有此签名:Future.addListener(GenericFutureListener<? extends Future<? super V>> listener)
。 ChannelPromise
仅扩展了Future<Void>
。
这种通用情况是有道理的,因为1.如果您有一个FutureListener<Future<Object>>
,则在将来完成时它可以处理任何Object
值; 2.由于V
是Object
,因此可以处理V
。因此,它可以收听Future<V>
。显然,对于V
而不是Object
的任何超类型也是如此。
当然,如果Java具有declaration-site variance,这些签名会简单得多,但是现在没有,并且可能很快也不会。
答案 1 :(得分:9)
似乎是为了符合GenericFutureListener<Future<? super T>>
之类的通用类型而创建的,该类型不够灵活,无法单独容纳GenericFutureListener<Future<Void>>
。
例如,如果您有类似这样的内容:
class GenericFutureListener<T> {}
public static <T> void m(GenericFutureListener<Future<? super T>> p) {
...
}
m(new GenericFutureListener<Future<? super Void>>() {}); // works,
m(new GenericFutureListener<Future<Void>>() {}); // does not work
不允许仅传入GenericFutureListener<Future<Void>>
。
答案 2 :(得分:2)
您已经注意到,Future<? super Void>
只能是虚无的未来,也可以是Object
的未来。
但是:
那为什么不只写《未来》呢?
几乎可以肯定,开发人员的意图是将“听众”限制为无效行为。但是,如果允许一个Future<Object>
,那么任何其他类型都可以用作Future
的值,因为Future<Object>
可以容纳String
(或任何其他类型)的结果
java.lang.Void
是final
类,它不允许任何子类,这实际上几乎将其完全限制为无效操作(除非在设置时调用new Object()
具有实用价值)未来的结果)
答案 3 :(得分:0)
是的,您可以将Future<Object>
与该侦听器一起使用,但是声明明确指出侦听器应该/不使用结果。
将其声明为GenericFutureListener<Future<Object>>
给人的印象是听众对结果做了一些事情。
答案 4 :(得分:0)
有时我们只关心任务是否完成。
像我这样的人可能更愿意返回Future<Void>
来表明任务没有结果。
虽然其他人可能更喜欢使用Future<Object>
或Future<?>
并使用null
作为结果。
我认为这个人同时遇到了Future<Void>
和Future<Object>
。因此,他使用Future<? super Void>
来适应这两种通用方法。