12

これはEffectiveJavaからのものです:

// Implementing a fromString method on an enum type
  private static final Map<String, Operation> stringToEnum
      = new HashMap<String, Operation>();

  static { // Initialize map from constant name to enum constant
    for (Operation op : values())
      stringToEnum.put(op.toString(), op);
  }

  // Returns Operation for string, or null if string is invalid
  public static Operation fromString(String symbol) {
    return stringToEnum.get(symbol);
  }

操作定数は、定数が作成された後に実行される静的ブロックからstringToEnumマップに配置されることに注意してください。各定数を独自のコンストラクターからマップに入れようとすると、コンパイルエラーが発生します。正当な場合はNullPointerExceptionが発生するため、これは良いことです。列挙型コンストラクターは、コンパイル時定数フィールドを除いて、列挙型の静的フィールドにアクセスすることは許可されていません。これらの静的フィールドはコンストラクターの実行時にまだ初期化されていないため、この制限が必要です。

私の質問はラインに関するものです:

「操作定数は、定数が作成された後に実行される静的ブロックからstringToEnumマップに配置されることに注意してください」。

コンストラクターが実行される前に静的ブロックが実行されると思いました。これらは、実際にはクラスのロード時に実行されます。

ここで何が欠けていますか?

4

3 に答える 3

13

あなたの質問を次のように理解しています:静的ブロックが実行される前に列挙型定数が初期化されるという保証があるのはなぜですか。答えはJLSにあり、具体的な例は#8.9.2.1にあり、次の説明があります。

静的初期化は上から下に行われます。

enums 定数は暗黙的に final static であり、静的初期化子ブロックの前に宣言されます。

編集

挙動は通常のクラスと変わりません。以下のコードは次のように表示されます。

In constructor: PLUS
PLUS == null MINUS == null

In constructor: MINUS
PLUS != null MINUS == null

In static initialiser
PLUS != null MINUS != null

In constructor: after static
PLUS != null MINUS != null
public class Operation {

    private final static Operation PLUS = new Operation("PLUS");
    private final static Operation MINUS = new Operation("MINUS");

    static {
        System.out.println("In static initialiser");
        System.out.print("PLUS = " + PLUS);
        System.out.println("\tMINUS = " + MINUS);
    }

    public Operation(String s) {
        System.out.println("In constructor: " + s);
        System.out.print("PLUS = " + PLUS);
        System.out.println("\tMINUS = " + MINUS);
    }

    public static void main(String[] args) {
        Operation afterStatic = new Operation ("after static");
    }    
}
于 2012-08-02T12:02:21.243 に答える
1

ブロックはstatic、クラスローダーがクラスをロードするときに、出現順に実行されます (複数の静的ブロックを持つことができます)。コンストラクターの前に実行されます。

于 2012-08-02T11:50:50.217 に答える
0

Operation定数は、静的ブロックに出現順に作成される静的フィールドです。

static { 
    // instantiate enum instances here
    ...
    // Initialize map from constant name to enum constant     
    for (Operation op : values())       
       stringToEnum.put(op.toString(), op);   
} 
于 2012-08-02T11:50:07.553 に答える