2012-02-01 5 views
16

静的フィールドへの不正な参照があるため、このコードはコンパイルされません。なぜこの列挙型コードは静的フィールドへの不正な参照ですか?

public enum Foo { 

    A, 
    B; 

    private Foo[] foos = new Foo[] { Foo.A }; 

} 

静的ではないフィールド初期化子から静的フィールドにアクセスできませんか?例:

public class Foo { 

    static int A; 

    private int[] foos = new int[] { Foo.A }; 

} 

これはうまくコンパイルされます。

最初の例では、foosを静的にコンパイルすることに注意してください。バイトコードに近いほぼ同等の、簡単な方法、で書き出さ

答えて

16

(§コンパイル時定数ではありません列挙型 の静的フィールドを参照するために、コンパイル時のエラーですhttp://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.9

のセクション8.9、Java言語仕様第3版をチェックしてください1535)、インスタンス初期化子ブロック またはインスタンス変数初期化子 の式の式から構成されます。 コンストラクタ、インスタンスイニシャライザブロック、またはインスタンス変数 イニシエータ式のenum定数eを参照するコンパイル時エラー、またはeの右側に宣言された同じ型の列挙定数 のコンパイル時エラーです。

このルールがなければディスカッション

、明らかに合理的なコードが原因列挙型に固有の初期化真円度に、実行時 で失敗するでしょう。 ( 円形度は、「自己型付けされた」静的フィールドと任意のクラスに存在する。) ここで失敗するコードの種類の例である:

enum Color { 
     RED, GREEN, BLUE; 
     static final Map<String,Color> colorMap = 
     new HashMap<String,Color>(); 
     Color() { 
      colorMap.put(toString(), this); 
     } 
    } 

この列挙型の静的初期化列挙定数のコンストラクタが実行されたときに、静的変数colorMapが であるため、 NullPointerExceptionがスローされます。上記の 制限により、そのようなコードはコンパイルされません。

7

、我々は、次を参照してください。

public final class Foo { 
    public static final Foo A = new Foo(); 
    public static final Foo B = new Foo(); 

    private Foo[] foos; 

    private Foo() { 
     this.foos = new Foo[] { Foo.A }; 
    } 
} 

あなたはA我々はAを読み込みコンストラクタを呼び出している初期化するためにそれを見ることができます。明らかに、コンストラクタでまだAは初期化されていません。

(結局のところ、このシンプルなコードはコンパイルん。それはちょうどあなたが期待するかもしれない何をしません。)

あなたはおそらく代わりにfoosインスタンス変数のFoo.values()をしたいです。

関連する問題