[英]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的過程如下:
在 C 的初始化鎖 LC 上同步。這涉及到等待當前線程可以獲取 LC。
如果 C 的 Class object 表明其他線程正在對 C 進行初始化,則釋放 LC 並阻塞當前線程,直到通知正在進行的初始化已完成,此時重復此步驟。
如果 C 的 Class object 表明當前線程正在對 C 進行初始化,那么這一定是遞歸請求初始化。 釋放 LC 並正常完成。
第 3 步是我們在這里采取的步驟。 Class A已經被當前線程初始化,所以我們處於遞歸初始化的情況。 於是直接放棄,直接正常完成,所以A.test還是null,B.test得到A.test的值null。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.