2012-03-30 8 views
0
public class StaticTest { 

    private static StaticTest stObj=new StaticTest(); 
    private static int VAR1=10; 
    private static final int VAR2=20; 

    public StaticTest() { 

     System.out.println("Var1 : "+VAR1); 
     System.out.println("Var2 : "+VAR2); 
    } 

    public static void main(String[] args) { 
     System.out.println("VAR1 after constrution : "+StaticTest.VAR1); 
    } 

} 

出力:のJava差

VAR1:0 VAR2:constrution後20 VAR1:10

なぜVAR1とVAR2は、この異なる挙動?

+1

VAR2は定数ですが、VAR1は単純な静的変数です。これは、stObjが初期化された後にVAR1が初期化されることを意味します。 VAR1が最初の呼び出しでは0(デフォルトのint値)、2番目の呼び出しでは10です。 – dexametason

答えて

0

VAR2は、クラスが初期化されたものを変更することはできません。

ここでの問題は、完全に初期化される前に変数を参照していることです。

private static StaticTest stObj=new StaticTest(); 
private static int VAR1=10; 
private static final int VAR2=20; 

クラス自身をロードするときに他の静的メンバーが初期化されています前に、クラスのインスタンスを作成しています。

Java Language Specifications for more details (Chapter 12)を確認してください。

(一般的には、独自の施工時にクラスのインスタンスを作成することは問題につながる:あなたはこれを避ける必要があります。)その値があらゆるに「焼き」されるように

+0

しかし、誰も変数を変更していませんか? – amicngh

+0

少なくともあなたが提供したコードに含まれていません –

+1

変数「VAR」は、最初は「0」で、「10」に設定することができます。 –

0

VAR1VAR2は変更できません。

これを試してみてください:クラスのインスタンスが、後でVARを変更することができ、一方、

private static int VAR1=10; 
private static final int VAR2=20; 

public static void main(String[] args) { 
    VAR1 = 25; 
    VAR2 = 35; // You'll find a compilation error here. 
} 
3

VAR2は、コンパイル時定数でありますコールサイト。したがって、に初期化されることを期待する前に、使用することは重要ではありません。 でない何かに変更すると、コンパイラに関する限り定数になります。

private static final int VAR2 = "xyz".length(); 

VAR1(出力に関して)と同じ動作が表示されます。

定数式の詳細については、section 15.28 of the JLSを参照してください。

+0

コンパイル時にVAR2が定数と見なされていますか? – amicngh

+0

@amicngh:それは*仮定*の問題ではありません - それはJLSに従うことの問題です。変数は静的で最終的であり、プリミティブ型であり、初期化式はコンパイル時の定数式です。 http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 –

+0

@JonSkeetを参照してください。そうですが、この質問にはそれ以上のものがあると思います(初期化順序に関して)。 – Bruno

5

静的フィールドは、宣言の順に1つずつ初期化されます。 具体的にはStaticTest stObjを最初に初期化します。これは、VAR1の初期化の前に実行されます。したがって、VAR1は印刷時にそのデフォルト値を保持します。

ただし、VAR2はコンパイル時定数なので、コンパイラはその初期化を最適化し、最初に初期化されます。そのようにして、変数の1つはコンストラクタを呼び出した時点で初期化され、もう1つは初期化されません。