[英]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規范的方式
在許多情況下,對程序變量(對象實例字段,類靜態字段和數組元素)的訪問可能看起來以與程序指定的順序不同的順序執行。
如果有子類和超級類。
不是真的回答這個問題,而是在這里問更多 - )。 剛剛遇到一個有趣的靜態字段初始化順序示例。 這是一個例子:
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.