簡體   English   中英

java.lang.Void 和 void 有什么區別?

[英]What is the difference between java.lang.Void and void?

在 API

“Void 類是一個不可實例化的占位符類,用於保存對表示 Java 關鍵字 void 的 Class 對象的引用。”

  1. 什么是“不可實例化”的占位符類? 什么時候使用java.lang.Void 如果類是“不可實例化的”,它有什么用?
  2. java.lang.Voidvoid有什么區別?

java.lang.Void類似於java.lang.Integer Integer是一種將原始類型int的值裝箱的方式。 Void是一種對原始類型void的值進行裝箱的方法。

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

正確的! 這就是使java.lang.Void “不可實例化”的原因。 :)

Java 類型系統的一個很好的特性是每個原始類型都有一個盒裝的等價物。 intIntegerlongLongbyteByte ... 並且voidVoid 如果Void存在,那將是奇怪和不對稱的。

“那么java.lang.Voidvoid有什么區別?”

簡單的。 void是原始類型。 Void是繼承自Object的引用類型。 它們的相似之處在於它們都沒有任何可能的值。 但是,從類型系統的角度來看,它們是兩種截然不同的類型。

“但我的程序中對Void沒有任何用處。”

而且我對GarbageCollectorMXBean沒有任何用處。 有些功能沒有非晦澀的用途。 沒關系。

Void最常見的用途是反射,但這並不是唯一可以使用它的地方。

void是一個關鍵字,表示函數不會產生值。

java.lang.Void是一個引用類型,那么以下是有效的:

 Void nil = null;

(到目前為止,它並不有趣......)

作為結果類型(返回值類型為Void的函數),它意味着函數 *always * 返回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 . When . When is invoked on that future, get() 時,刪除完成返回 null`。 可以用Callable寫一個類似的例子。

另一個用例是沒有值的Map ,即Map<T,Void> 這樣的映射的行為類似於Set<T> ,那么當沒有Set的等效實現時它可能很有用(例如,沒有WeakHashSet ,那么可以使用WeakHashMap<T,Void> )。

Void唯一的一點是持有Void.TYPE ,它有點像void.class 如果您對返回void的方法有反射引用,並且您獲得了它的返回類型,那么它將返回Void.TYPE

您不能也不應該將其用於其他任何事情。

Void 是 void 的一個自動裝箱功能(從 JDK 1.5 開始)。

好吧,它的自我解釋是 Void 是引用,而 void 是原始類型。

那么,哪里有要求必須使用 Void ???

泛型類型的一種常見用法,我們不能使用原始類型。

比如說,在 Android AsyncTaks<Params, Progress, Result>的情況下,如果我不想獲得 Progress 更新怎么辦。 我不能在這里使用 void (原始類型) 我們需要 java.lang.Void

另一個使用Void的例子是SwingWorker

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

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);
    }

我個人是這樣使用它的:

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

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

我的理由是這樣的:

基於用戶輸入的計算可能會創建您的系統可能需要的新類型分配。

該動作可能會保持其同名,因為在客戶端的眼中它正在執行它所說的內容,但是在系統內的子層中正在發生等效的動作,但具有完全不同的類型,只有您的系統應該知道的類型。

這可能與“自相似”原則有關,其中系統由與其自身相似的較小組件組成,因此重用具有不同類型和相似名稱的接口可能是合乎邏輯的,該系統還意味着具體化(將抽象的東西轉換為real) 是系統狀態固有的,因此用戶對立即讀取返回值不感興趣,但目標依賴於對象的狀態變化。

現在這個特定示例是針對原子操作的,TBH 我想不出可能需要這樣做的不同情況,原因是本機原子操作依賴於時空(空間 = 內存范圍)快照才能准確執行.

這種新的分配對客戶來說並不重要,而只對系統的功能很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM