2011-11-14 15 views
0

私は、次のクラスしているとField.get(ヌル):Aは静的ブロックと静的でない原始的なデータフィールド

public class A { 

    static { 
     B.load(A.class); 
    } 

    public static final C field1 = new C("key1", "value1"); 

    public static final C field2 = new C("key2", "value2"); 

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

} 

public class B { 

    public static void load(Class<?> clazz) { 
     for (Field field : clazz.getFields()) { 
      try { 
       System.out.println("B.load -> field is " + field.get(null)); 
      } catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
      } catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

public class C { 

    private final String key; 

    private final String value; 

    public C(String key, String value) { 
     super(); 
     this.key = key; 
     this.value = value; 
    } 

    public String getKey() { 
     return this.key; 
    } 

    public String getValue() { 
     return this.value; 
    } 

    @Override 
    public String toString() { 
     return "C [key=" + this.key + ", value=" + this.value + "]"; 
    } 

} 

です実行私は得る:

B.load -> field is null 
B.load -> field is null 
C [key=key1, value=value1] 

field.get(null)は、実行時にnull値を返すのはなぜですか?私は例外もなく、この動作はJavadocによって説明されていないようです。

答えて

1

すべての静的メンバーは(静的ブロック用に)実行され、宣言の順序で(静的フィールド用に)初期化されると思います。クラスAクラスの静的ブロックをクラスの最後に配置するか、少なくとも静的フィールドの後に配置してみてください。 Lemmeは違いがあるかどうかを知っています。

EDIT:プリミティブと弦楽のための行動に関する情報...

あなたは、プリミティブまたはリテラル文字列(または静的のいずれかであることの結果を評価できる表現をされ、最終的な静的フィールドを持っている場合これら)は、コンパイル時定数と見なされます。基本的には、このような値を設定しても、コンストラクタの呼び出しやまだ初期化されていない可能性のある他のフィールドに対する評価など、「計算」は必要ありません。文字列はプリミティブではありませんが、コード内の文字列リテラルを可能にするための特別な処理が行われています。

これは、クラスがロードされ、初期化の準備が整うとすぐに、そのようなフィールドを割り当てることができることを意味します。それに関する仕様の詳細はわかりませんが、反射を試してみると、これが起こっている必要があります。 Java言語仕様の

以下のセクションでは、この動作を理解するのに関連しています

+0

おかげで、それは問題を解決しますが、私は理解していないものがまだあります。 Cの代わりにプリミティブなデータ型を使用すると問題が発生しないのはなぜですか(例:static int field1 = 1およびstatic int field2 = 2 B.loadがフィールドの前に宣言されている静的ブロックを含む)? – Laurent

+0

@Laurent私はいくつかの情報で編集します。 –

1

クラスAでは、静的フィールドの前に、の静的関数の呼び出しを宣言する必要があります。

public static final C field1 = new C("key1", "value1"); 

public static final C field2 = new C("key2", "value2"); 

static { 
    B.load(A.class); 
} 

Java tutorialはそれを説明する:

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

関連する問題