Java.lang. Void 和 Void 的区别是什么?

空气污染指数

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

  1. 什么是“不可实例化”的占位符类?什么时候使用 java.lang.Void?如果类是“不可实例化的”,那么它有什么用呢?
  2. java.lang.Voidvoid有什么不同?
37246 次浏览

Void只有一点是用来容纳 Void.TYPE的,有点像 void.class。如果您有一个返回 void的方法的反射引用,并且您得到了它的返回类型,那么它将返回 Void.TYPE

你不能,也不应该把它用在其他地方。

java.lang.Void类似于 java.lang.IntegerInteger是装箱基元类型 int的值的一种方法。Void是装箱基元类型 void的值的一种方法。

“但是等等,void没有任何可能的值!”

没错! 这就是 java.lang.Void“不可实例化”的原因。 :)

Java 类型系统的一个很好的特性是,每个基元类型都有一个装箱的等价物。intInteger longLong byteByte voidVoid。如果 Void没有存在,那将是奇怪和不对称的。

“那么 java.lang.Voidvoid有什么区别呢?”

放松。void是基元类型。Void是从 Object继承的引用类型。它们很相似,因为它们都没有任何可能的值; 但是从类型系统的角度来看,它们是两种非常不同的类型。

“但在我的程序中,Void没有任何用处。”

我没有使用任何 GarbageCollectorMXBean在我的。一些功能不 非晦涩的使用。这是没关系的。

Void最常见的用途是用于反射,但这并不是可以使用它的唯一地方。

void是一个关键字,表示函数不会产生值。

java.lang.Void是一个引用类型,那么以下内容是有效的:

 Void nil = null;

(到目前为止,这并不有趣... ...)

作为结果类型(返回值类型为 Void的函数) ,它意味着函数 * 总是 * 返回 null(它不能返回除 null以外的任何东西,因为 Void没有实例)。

 Void function(int a, int b) {
//do something
return null;
}

为什么我想要一个 一直都是返回 null 的函数?

在泛型发明之前,我没有 Void的用例。

对于泛型,有一些有趣的情况。例如,Future<T>是另一个线程执行的异步操作结果的持有者。Future.get将返回操作值(类型为 T) ,并将阻塞直到执行计算。

但是... 如果没有什么可以回去呢?简单: 使用 Future<Void>。例如,在 Google App Engine 中,异步数据存储服务 delete操作返回一个 future ure. Whenget () is invoked on that future,null‘ ,返回 之后,删除完成。我们可以用 可呼叫写一个类似的例子。

另一个用例是没有值的 Map,即 Map<T,Void>。这样的映射行为类似于 Set<T>,那么当没有 Set的等价实现时(例如,没有 WeakHashSet,那么可以使用 WeakHashMap<T,Void>) ,它可能是有用的。

Void 是 Void 的 AutoBoxing 特性(自 JDK 1.5以来)。

它自我解释了,无效是参考,而无效是一个 原始类型。

那么,需求从何而来必须使用 Void? ? ?

泛型类型的一个常见用法是不能使用原语。

比如说,在 Android AsyncTaks<Params, Progress, Result>的情况下,如果我 不想获取 Progress 更新。我不能使用 void (原语类型) 这里我们需要 java.lang 空白

Void 是有用的,因为有时需要在方法本身之外指定方法的返回类型。

以这个 Java 8 lambda 表达式为例,它使用一个名为 checkBenefitConcertInCentralPark的方法检查 EventResource 对象是否具有某些属性,该方法传递给方法 checkCreatedEvent:

eventChecker.checkCreatedEvent(TestEvents::checkBenefitConcertInCentralPark);

checkBenefitConcertInCentralPark方法的定义如下(注意 Void 的使用) :

    public static Void checkBenefitConcertInCentralPark(EventResource eventResource) {
// JUnit code here...
// assertThat(blablabla  :)  )


return null; // we can only return null at the end of a method when returning Void
}

然后将 checkBenefitConcertInCentralPark方法传递给 checkCreatedEvent方法。

    // Function<EventResource, Void> describes the checkBenefitConcertInCentralPark method
public void checkCreatedEvent(Function<EventResource, Void> function) {
function.apply(this.eventResource);
}

使用 Void的另一个例子是 SwingWorker

new SwingWorker<Void, Integer> () {
@Override
protected Void doInBackground(){
...
}
@Override
protected void process(List<Integer> chunk){
...
}
@Override
public void done(){
...
}
}.execute();

我个人是这样使用的:

@FunctionalInterface
interface MyPackagePrivateInterface<T, Next> {
//Returns next
Next compareAndSwap(T prev);
}


@FunctionalInterface
public interface ClientPublicInterface<T> extends MyPackagePrivateInterface<T, Void> {
}

我的理由是:

基于用户输入的计算,可能会创建新的类型分配,您的系统可能需要。

这个动作可以保留它的同名字,因为在客户端的眼中,它正在执行它所说的,但是在系统的子层中,一个等效的动作正在发生,但是是用完全不同的类型,类型,只有你的系统应该知道。

这可能与“自相似性”原则有关,在这个原则中,一个系统是由与自身相似的较小组件组成的,因此重用具有不同类型和相似名称的接口可能是合乎逻辑的,这个系统还意味着具体化(将抽象的东西转化为真实的东西)是系统状态的本质,因此用户对立即读取返回值不感兴趣,但目的依赖于对象状态的变化。

现在这个特殊的例子是关于原子操作的,TBH 我想不出还有什么不同的情况需要这样做,原因是本机原子操作依赖于时间空间(space = memory scope)快照来准确执行。

这种新的分配对于客户端并不重要,重要的只是系统的功能。