Java泛型中Void和无界通配符有什么区别?

时间:2012-10-18 19:17:12

标签: java generics

Vone类型的对象与Java泛型中的无界通配符类型有什么区别?我的意思是我理解<?>的使用,以及在反射方面使用Void,但当我看到

的Java源代码时,我有点好奇
java.util.concurrent.AbstractExecutorService

及其方法

public Future<?> submit(Runnable task) {
    ...
    RunnableFuture<Void> ftask = new TaskFor(task, null);
    ...
    return ftask;

在方法内部,它使用RunnableFuture&lt; Void&gt;而不是RunnableFuture&lt;?&gt;

有人能帮我理解这背后的原因吗?感谢

3 个答案:

答案 0 :(得分:13)

Void是一个特殊类,用于表示返回值。虽然Void 本身没有什么特别之处,但它不能(并且永远不会)实例化,因此唯一可能的值始终为null。它用于两件事:

  1. 说通用方法或类没有返回值。
  2. 使用void在Java反射中表示Void.TYPE返回类型。例如,请参阅How to determine by reflection if a Method returns 'void'
  3. 因此它与通配符非常不同,通配符不是实际的类,而是在编译时表示一个特定的 unknown 类型。在运行时,它与所有其他泛型类型一样erased


    关于submit方法。以下是JDK 6的两个实现:

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Object> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    

    和JDK 7:

    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    

    正如您所看到的,仅在JDK 7中将类型更改为Void,可能是因为它在概念上更有意义。但由于无法更改方法的接口(出于兼容性原因并且因为该方法实现了ExecutorService接口的Future<?> submit(Runnable task)),因此返回类型Future<?>保持不变。这是我的解释。

答案 1 :(得分:4)

Void不是通配符,它​​表示根本没有值返回。

Void javadoc ...

答案 2 :(得分:3)

Void是void的对象表示。 void从方法返回任何内容时,Void ALWAYS返回null。这是因为void不是一个对象,因此不能与泛型一起使用。当您不需要任何返回值时,使用Void with Futures会很高兴。