169

有一个VoidJava——大写 V——引用类型。我见过它使用的唯一情况是参数化Callables

final Callable<Void> callable = new Callable<Void>() {
            public Void call() {
                foobar();
                return null;
            }
        };

VoidJava引用类型还有其他用途吗?它可以被分配除 之外的任何东西null吗?如果有,你有例子吗?

4

11 回答 11

123

Void已成为您不感兴趣的通用参数的约定。没有理由应该使用任何其他不可实例化的类型,例如System.

它也经常用于例如Map值(尽管Collections.newSetFromMap用作Boolean映射不必接受null值)和java.security.PrivilegedAction.

于 2009-03-13T18:35:02.450 回答
52

您可以使用反射创建 Void 实例,但它们对任何事情都没有用。Void 是一种表示泛型方法不返回任何内容的方式。

Constructor<Void> constructor = Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
Void v = constructor.newInstance();
System.out.println("I have a " + v);

打印类似的东西

I have a java.lang.Void@75636731
于 2009-03-13T21:43:34.120 回答
28

Future<Void>像魅力一样工作。:)

于 2009-03-13T18:11:48.840 回答
20

鉴于没有公共构造函数,我会说它不能被分配除null. 如您的示例所示,我仅将其用作“我不需要使用此通用参数”的占位符。

它也可以用于反射,从它的Javadoc说:

Void 类是一个不可实例化的占位符类,用于保存对表示 Java 关键字 void 的 Class 对象的引用。

于 2009-03-13T18:12:00.447 回答
19

所有原始包装类(IntegerByteBooleanDouble等)都包含对静态字段中相应原始类的引用TYPE,例如:

Integer.TYPE == int.class
Byte.TYPE == byte.class
Boolean.TYPE == boolean.class
Double.TYPE == double.class

Void最初被创建为在某个地方放置对void类型的引用:

Void.TYPE == void.class

但是,使用Void.TYPE. 当您使用void.class它时,您会更清楚地知道您正在使用该void类型进行操作。

顺便说一句,我上次尝试时,BeanShell无法识别void.class,所以你必须在Void.TYPE那里使用。

于 2009-03-13T22:20:35.187 回答
11

当您使用访问者模式时,当您想确保返回值为 null 时,使用 Void 而不是 Object 会更简洁

例子

public interface LeavesVisitor<OUT>
{
   OUT visit(Leaf1 leaf);

   OUT visit(Leaf2 leaf);
}

当您将实现您的访问者时,您可以明确地将 OUT 设置为 Void 以便您知道您的访问者将始终返回 null,而不是使用 Object

public class MyVoidVisitor implements LeavesVisitor<Void>
{
    Void visit(Leaf1 leaf){
        //...do what you want on your leaf
        return null;
    }

    Void visit(Leaf2 leaf){
        //...do what you want on your leaf
        return null;
    }
}
于 2013-12-12T10:29:06.877 回答
6

在泛型之前,它是为反射 API 创建的,用于保存由 Method.getReturnType() 返回的 TYPE,用于 void 方法,对应于其他原始类型类。

编辑:来自 Void 的 JavaDoc:“Void 类是一个不可实例化的占位符类,用于保存对表示 Java 关键字 void 的 Class 对象的引用”。在泛型之前,我知道除了反射之外没有其他用途。

于 2009-03-14T21:41:22.443 回答
3

由于你不能实例化 Void,你可以使用Apache commons Null object,所以

Null aNullObject = ObjectUtils.Null;
Null noObjectHere = null;

在第一行,你有一个对象,所以aNullObject != null成立,而在第二行没有引用,所以noObjectHere == null成立

为了回答发帖人的原始问题,其用法是区分“无”和“无”,它们是完全不同的事物。

PS:对空对象模式说不

于 2015-01-07T19:34:08.307 回答
2

Void被创建来包装它的原始void类型。每个原始类型都有其对应的引用类型。Void用于实例化泛型类或使用泛型方法,您不感兴趣的泛型参数。这是一个示例...

public void onNewRegistration() {
    newRegistrationService.createNewUser(view.getUsername(), view.getPassword(),
            view.getInitialAmount(), view.getCurrency(), new AsyncCallback<Void>() {
      @Override
      public void onFailure(Throwable caught) {
          
      }

      @Override
      public void onSuccess(Void result) {
        eventBus.fireEvent(new NewRegistrationSuccessEvent());
      }
    });
  } 

在这里,如您所见,我不希望服务器提供任何我要求创建新注册的东西,但public interface AsyncCallback<T> { .... }它是一个通用接口,所以我提供,Void因为泛型不接受原始类型

于 2012-04-21T07:30:08.550 回答
0

当您不需要对象时,它也常用于 Async-IO 完成回调Attachment。在这种情况下,您为 IO 操作指定 null 并实现CompletionHandler<Integer,Void>.

于 2014-08-10T15:33:42.987 回答
0

这可能很少见,但有一次,我Void在方面类中使用过。

这是一个在具有@Log注释的方法之后运行的方面,如果方法返回类型不是 void,则记录返回的方法和一些信息。

 @AfterReturning(value = "@annotation(log)", 
       returning = "returnValue", 
       argNames = "joinPoint, log, returnValue"
      )
    public void afterReturning(final JoinPoint joinPoint, final Log log,
            final Object returnValue) {

            Class<?> returnType = ((MethodSignature) joinPoint.getSignature())
            .getReturnType();
           if (Void.class.isAssignableFrom (returnType)) ) {
            //Do some log
         }
}
于 2015-12-13T08:09:38.997 回答