簡體   English   中英

Java:初始化靜態最終字段的順序是什么?

[英]Java : in what order are static final fields initialized?

好吧,所以說我有一個看起來像這樣的課程:

public class SignupServlet extends HttpServlet {
    private static final Logger SERVLET_LOGGER=COMPANYLog.open(SignupServlet.class);
    private static final ExceptionMessageHandler handler = new ExceptionMessageHandler();   
    private static final SignupServletObservableAgent signupObservableAgent = 
        new SignupServletObservableAgent(null, SERVLET_LOGGER);
}

我可以指望類加載器按順序初始化這些字段,這樣我可以依賴SERVLET_LOGGER在signupObservableAgent之前實例化嗎?

是的,它們按照它們在源中出現的順序進行初始化。 您可以閱讀The Java Language Specification,§12.4.2所有詳細信息。 見步驟9,其中包括:

...以文本順序執行類的類變量初始值設定項和類的靜態初始化程序,或接口的字段初始值設定項,就好像它們是單個塊一樣,除了最終的類變量和接口的字段,其值是compile-時間常數首先初始化...

我認為可以重新排序靜態字段的初始化。 至少這是我理解JMM規范的方式

在許多情況下,對程序變量(對象實例字段,類靜態字段和數組元素)的訪問可能看起來以與程序指定的順序不同的順序執行。

如果有子類和超級類。

  1. EX:'A':超級'B':子類,它擴展了超類'A'
  2. 當B類加載時,A類也會加載
  3. 所有靜態變量都從“A”和“B”類獲取具有默認值的內存
  4. 然后靜態成員(靜態變量,靜態塊)以“A”類的從上到下的順序執行,然后按照它們聲明的順序執行“B”類。 最后自動從子類執行main方法。

不是真的回答這個問題,而是在這里問更多 - )。 剛剛遇到一個有趣的靜態字段初始化順序示例。 這是一個例子:

   public class Foo {

    private static final Long result = method1();

    private static String string = "something";

    private static Long method1() {
        if (string == null) {
            throw new IllegalStateException("BOOM");
        }
        return 1L;
    }

    public static void main(String[] args) {
        System.out.println("here");
    }
}

這將產生IllegalStateException。 我知道這里的順序是首先我們評估調用method1()並繞過“string”值初始化的“result”字段。 “string”意味着是一個常量,但是在編寫測​​試時我忘了放一個“final”修飾符。 但是這樣的情況應該在運行時處理嗎? 當我們調用“if(string == null)”時,JRE是否足夠智能去驗證“string”是否尚未初始化並初始化它?

在這里您可以使用靜態塊來保證執行順序。

public class SignupServlet extends HttpServlet {
   private static final Logger SERVLET_LOGGER;
   private static final ExceptionMessageHandler handler;
   private static final SignupServletObservableAgent signupObservableAgent;

   static {
      SERVLET_LOGGER = COMPANYLog.open(SignupServlet.class);
      handler = new ExceptionMessageHandler();
      signupObservableAgent = new SignupServletObservableAgent(null, SERVLET_LOGGER);
   } 
}

暫無
暫無

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

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