簡體   English   中英

最終變量首先初始化

[英]final variable initialized first

我在這里閱讀這個問題: Java:初始化靜態最終字段的順序是什么?

根據答案

“除了最終的類變量和接口的字段,其值是編譯時常量首先被初始化......”

我認為這是不正確的,因為以下將失敗:

static {
    String y = x;
}

public static final String x = "test";

在靜態塊中,無法識別x 如果答案是正確的,有人可以評論嗎?

初始化順序不會改變JLS在各種情況下聲明變量之前不允許引用變量的事實。 這在JLS§8.3.3中描述:

使用聲明在使用后以文本形式出現的類變量有時會受到限制,即使這些類變量在范圍內(第6.3節)。 具體來說,如果滿足以下所有條件,則為編譯時錯誤:

  • 在使用類變量之后,類或接口C中的類變量聲明以文本形式出現;

  • 在C的類變量初始化程序或C的靜態初始化程序中使用是一個簡單的名稱;

  • 使用不在作業的左側;

  • C是封閉使用的最內層類或接口。

這就是你的代碼得到這個編譯erorr的原因:

錯誤:非法轉發參考

首先初始化作為常量變量的靜態字段的聲明確實在JLS§12.4.2中定義:

  1. 否則,記錄當前線程正在進行C的Class對象初始化並釋放LC的事實。

    然后,初始化C的靜態字段,它們是常量變量(§4.12.4,§8.3.2,§9.3.1)。

...

  1. 接下來,按文本順序執行類的類變量初始值設定項和類的靜態初始值設定項,或接口的字段初始值設定項,就好像它們是單個塊一樣。

如您所見,常量變量在步驟6中初始化,但在步驟9中初始化。

這表明了這種行為:

public class Example {
    static String y;
    static  {
         y = foo();
    }

    static String foo() {
        return x.toUpperCase();
    }

    public static final String x = "test";

    public static void main(String[] args) throws Exception {
        System.out.println(x);
        System.out.println(y);
    }
}

編譯並輸出:

test
TEST

如果你更改了x行,那么它就不再是常數了:

public static final String x = Math.random() < 0.5 ? "test" : "ing";

它編譯,但隨后將失敗,因為xnully = foo();


為避免疑義:我建議使用方法來初始化這樣的字段。 :-)

正如這個答案所述:

......它們按照它們出現在源中的順序進行初始化。

你是絕對正確的,你的例子失敗了,因為你試圖使用在使用之后聲明的變量。 由於靜態塊是按源代碼的順序執行的,因此您絕對正確,應該建議並編輯該答案,因為此語句無效:

除了最后的類變量...首先被初始化。

暫無
暫無

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

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