19

重複の可能性:
列挙型のコンストラクターが静的フィールドにアクセスできないのはなぜですか?

enum Test {
  e1,e2;      

  int i=0;
  static int j=5;

  Test(){
    System.out.println(i+" "+j);
  }
}

上記のコードでは、コンストラクターはインスタンス変数にアクセスできますが、静的変数 J にはアクセスできません。

私は他の著者に関連する答えを読みましたが、すべてがJ(静的フィールド)の初期化の前にe1とe2が初期化されたと言っていますが、Java仕様によれば、クラスがメモリにロードされたときにすべての静的フィールドが初期化されました。コンストラクタ。したがって、Test() コンストラクターを実行する前に、静的変数 j を初期化する必要があります。私は制限を理解することができません.どんな体でも私に理解させることができます.私はすでに列挙型のコンストラクターが静的フィールドにアクセスできないのはなぜですか? しかし、私は次のような答えには満足していません:-静的フィールドがすべて初期化される前にコンストラクターが呼び出されます。

enum のような単純なクラスを使用した別の例を考えてみましょう

class Test{
  public static final Test t=new Test();
  static int a=5;

  Test(){
    System.out.println(a);  
  }

  public static void main(String[] args) {
  }
}

ここでは、コンストラクターは static フィールドの初期化の前に実行され、print 0 としても実行されます (JVM が初期化を行ったように)。しかし、コンパイル エラーや実行時の問題はありません。次に、同じことが列挙型で起こらないのはなぜですか。

4

2 に答える 2

6

列挙型が実際にクラスとしてどのように見えるかを想像すると、それは理にかなっています。

public class Test {
  // Imagine you cannot move these two statements:
  public static final Test e1 = new Test();
  public static final Test e2 = new Test();

  int i=0;
  static int j=5;

  private Test(){
    System.out.println(i+ " " + j);
  }

  static int getJ() {
    return j;
  }


  public static void main(String[] args) {
    System.out.println(Test.getJ());
  }
}

これは以下を出力します:

0 0
0 0
5

(理論的なものではなく)具体的な例を共有できる場合は、静的フィールドの制限にもかかわらず、コードを再設計して目的の結果を達成する方法を提案できます。

于 2012-11-23T09:00:41.417 に答える
3

問題は、静的フィールドの初期化中に列挙型のインスタンスが作成されることです。そして、静的フィールドの初期化前に作成しました。それらは静的な配列値にあり、静的にアクセスできる必要があるため、理にかなっています。また、「列挙型のコンストラクターが静的フィールドにアクセスできないのはなぜですか?」の回答で述べたように、これがすべてのユーザー定義の静的フィールドの初期化の前に発生するのは残念です。しかし、スワップされた場合、静的初期化で列挙型インスタンスにアクセスできなかったため、列挙型値の作成前と作成後の両方で静的ブロックを許可する必要があります。

enum値の初期化がEnumクラスに関係しているため(およびJVMによって特別に処理されているため(このロジックはEnumクラス自体にはありません)、または列挙値の前に静的フィールドを配置できないため)、問題が発生するかどうかはわかりません。

なぜその方法は少数の人しか答えられないのか (例: javadoc で Enum の作成者として言及されている Josh Bloch と Neal Gafter、そしておそらく未知の他の人)

于 2012-11-23T08:30:38.337 に答える