簡體   English   中英

Static 相互引用的變量初始化?

[英]Static Variable Initialization that reference each other?

這與 static 變量初始化順序有些關系,但這個問題並沒有真正回答我的問題。

當我運行以下代碼時,我預計會發生未定義的行為或無限遞歸的事情:

class A {
    static File test = B.test;
    public static void main(String[] args) {
         System.out.println(A.test);
         System.out.println(B.test);
    }
}
class B {
     static File test = A.test;
}

但是,相反,我看到:

null
null

為什么會這樣?

答案來自JLS section 12.4 我們從 12.4.1 開始:

12.4.1。 初始化發生時

class 或接口類型 T 將在第一次出現以下任何一項之前立即初始化:

  • T 是一個 class 並且創建了一個 T 的實例。

  • 調用 T 聲明的 static 方法。

  • 分配了 T 聲明的 static 字段。

  • 使用由 T 聲明的 static 字段,並且該字段不是常量變量(第 4.12.4 節)。

當調用A.main時,第三個子句適用,因此必須初始化 class A(以及擴展名A.test )。 A.test的初始化觸發上面的第四個子句,這意味着 B 現在必須被初始化。 B 現在必須訪問 A 的字段,但 A 尚未初始化。

我們現在需要深入研究第 12.4.2 節:

12.4.2。 詳細的初始化過程... 對於每個class或接口C,都有一個唯一的初始化鎖LC。 從 C 到 LC 的映射由 Java 虛擬機實現自行決定。 那么初始化C的過程如下:

  1. 在 C 的初始化鎖 LC 上同步。這涉及到等待當前線程可以獲取 LC。

  2. 如果 C 的 Class object 表明其他線程正在對 C 進行初始化,則釋放 LC 並阻塞當前線程,直到通知正在進行的初始化已完成,此時重復此步驟。

  3. 如果 C 的 Class object 表明當前線程正在對 C 進行初始化,那么這一定是遞歸請求初始化。 釋放 LC 並正常完成。

第 3 步是我們在這里采取的步驟。 Class A已經被當前線程初始化,所以我們處於遞歸初始化的情況。 於是直接放棄,直接正常完成,所以A.test還是null,B.test得到A.test的值null。

暫無
暫無

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

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