2

構成ファイルからいくつかのログ メッセージを読み込もうとしていますが、enum名前を s と入力するときにタイプミスに遭遇するのではなく、を介してそれらの名前を参照したいと思いますString。だからここに私のセットアップがあります:

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());
        }

        //...
    }
}

私の懸念は、 s が初期化Logされる前に静的初期化子が実行されない、いくつかのフリンジ シナリオがあるかもしれないということです。enum私はコードをテストしましたが、これまでのところ正常に動作し、論理的には、静的初期化子が最初に実行されないMessage可能性があることはわかりません (参照は を通過Logする必要があるためLog.Message.IOEXCEPTION)。それでも、私はセットアップについて少し不安であり、アプリがクラッシュする可能性のある抜け穴を残したくありません. それで、これは安全ですか?

4

1 に答える 1

2

あなたの懸念は、列挙型がその外部クラスの静的初期化なしで何らかの方法でアクセスされることですが、これは不可能です。列挙型は外部クラス メンバーにアクセスします。

private Message() {
    text = MESSAGES.getProperty(name());
}   //        ^ static field of Log

まだアクセスしていない場合は、アクセスMESSAGESするとロードされて初期化されます。Log

「静的イニシャライザが最初に実行されなかった理由がわかりません (メッセージへの参照は Log.Message.IOEXCEPTION などのログを通過する必要があるため)」

外部クラス名を介してネストされたクラスにアクセスしても、外部クラスは初期化されません。

記録として、クラスが初期化される原因のリストを次に示します ( JLS 12.4.1 )。

  • T はクラスであり、T のインスタンスが作成されます。

  • T はクラスであり、T によって宣言された静的メソッドが呼び出されます。

  • T によって宣言された static フィールドが割り当てられます。

  • T によって宣言された静的フィールドが使用され、そのフィールドは定数変数ではありません (§4.12.4)。

  • T は最上位クラス (§7.6) であり、T (§8.1.3) 内に字句的にネストされた assert ステートメント (§14.10) が実行されます。

(Emboldened は、Log初期化の原因となるものです。)

静的で最終的なものMESSAGESですが、JLS から見れば定数変数ではありません。定数変数は、最終変数で次のように定義されます。

最終型で、コンパイル時の定数式で初期化されるプリミティブ型または String 型の変数...

于 2014-02-09T19:26:57.017 に答える