Java 空白引用类型的用途?

有一个 JavaVoid——大写的 V —— 引用类型。唯一的情况下,我曾经看到它使用的是参数化 Callable

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

JavaVoid引用类型还有其他用途吗?除了 null还能分配其他任何东西吗?如果是,你有例子吗?

85998 次浏览

考虑到有 没有公共建设者,我会说,它不能被分配以外的任何其他 null。我只是用它作为“我不需要使用这个通用参数”的占位符,如您的示例所示。

根据 贾瓦多克的说法,它也可以用于反思:

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

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

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

您可以使用反射创建 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

所有基元包装类(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

在泛型之前,它是为反射 API 创建的,用于保存 Method.getReturn nType ()为 void 方法返回的 TYPE,与其他基元类型类对应。

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

创建 Void是为了包装其基元 void类型。每个基元类型都有其对应的 Reference 类型。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,因为通用接口不接受基本类型

当您使用 访客模式时,如果您想确保返回值为 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;
}
}

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

因为不能实例化 Void,所以可以使用 Apache commons Null 对象,所以

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

在第一行,您有一个对象,所以 aNullObject != null保持,而在第二行没有引用,所以 noObjectHere == null保持

回答海报原来的问题,这个用法是区分“没有”和“没有”,这是完全不同的事情。

附言: 拒绝空对象模式

这种情况可能很少见,但是我曾经在方面类中使用过 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
}
}