我試圖從配置文件中加載一些日誌消息,但我仍然希望通過enum
來引用它們的名稱,而不是像String
那樣輸入名稱時打開自己的typographcial錯誤。因此,這裏是我的設置:外部類中的靜態初始化器是否保證在內部枚舉初始化之前運行?
public class Log {
private static final Logger LOGGER = Logger.getLogger(Log.class);
private static final String MESSAGES_FILE_PATH = "conf/log_message.conf";
private static final Properties MESSAGES = new Properties();
static {
try {
MESSAGES.load(new FileInputStream(new File(MESSAGES_FILE_PATH)));
}
catch(IOException ioe) {
LOGGER.fatal("Unable to load log messages from file: " + MESSAGES_FILE_PATH, ioe);
}
}
public enum Message {
//Main
PROGRAM_EXIT,
THREAD_INTERRUPTED,
FATAL_TERMINATING_ERROR,
SHUTDOWN_HOOK_EXCEPTION,
IO_READ_ATTEMPT,
IO_READ_FAILURE,
IO_WRITE_ATTEMPT,
IO_WRITE_FAILURE,
IOEXCEPTION,
//...
private final String text;
private Message() {
text = MESSAGES.getProperty(name());
}
//...
}
}
我擔心的是,可能會有一些邊緣情形,其中enum
s的初始化之前在Log
靜態初始化不運行。我已經測試了代碼,到目前爲止它工作正常,並且從邏輯上看,我沒有看到靜態初始化程序如何能夠首先運行而不是(因爲引用Message
必須經過Log
,例如Log.Message.IOEXCEPTION
)。不過,我對安裝有點不安,並且不想爲應用程序崩潰留下任何可能的漏洞。那麼,這是安全的嗎?
啓動和初始化過程詳見JLS。 –
我在[JLS詳圖初始化](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.5)中看到的唯一一件事就是:'如果C是一個類而不是接口,它的超類SC尚未初始化,然後遞歸執行SC的整個過程。如果有必要的話,先驗證並準備好SC。但是'Message'不是'Log'的擴展,它是一個內部類,我沒有看到任何細節將其作爲保證順序。不過,也許我在瀏覽JLS時錯過了一些東西。 – asteri