2016-08-03 8 views
1

次のJavaコードでは、Insectクラスはビートルクラスによって継承されています。Java - このコードの初期化の順序は何ですか?

class Insect { 

    private int i = 9; 
    protected int j; 

    Insect() { 
     System.out.println("i = " + i + ", j = " + j); 
     j = 39; 
    } 
    private static int x1 
      = printInit("static Insect.x1 initialized"); 

    static int printInit(String s) { 

     System.out.println(s); 
     return 47; 
    } 
} 

public class Beetle extends Insect { 

    private int k = printInit("Beetle.k initialized"); 

    public Beetle() { 
     System.out.println("k = " + k); 
     System.out.println("j = " + j); 
    } 
    private static int x2 
      = printInit("static Beetle.x2 initialized"); 

    public static void main(String[] args) { 
     System.out.println("Beetle constructor"); 
     Beetle b = new Beetle(); 
    } 
} 

出力はどうにかして複雑です。

静的Insect.x1は

静的Beetle.x2は

を初期化する初期化

ビートルコンストラクタ

I 0

Beetle.kが

Kを初期化= = 9、J = 47j = 39

この特定の例での初期化の順序は何ですか?

なぜx1はx1の後に即座に初期化されるのですか?そして、なぜ、メインメソッド(System.out.println("Beetle constructor");)の最初の行は、 x1とx2の初期化の後にを実行したのですか?とても楽しいです。

派生クラスのコンストラクタは、パラメータを持たずにスーパーキーワードを使用する場合を除き、自動的に基本クラスのコンストラクタを呼び出します。私は変数がコンストラクタの前に初期化され、静的変数は他の変数の前に初期化されることを知っています。

答えて

4

x1およびx2は静的です。これは、クラスがロードされるときに初期化されることを意味します。 mainメソッドはBeetleであるため、mainを呼び出す前にクラスをロードする必要があります。このため、最初に表示されるのはx1x2の初期化です。なぜそれらの2つの順序がそのままであるのか分からない。

mainSystem.out.println("Beetle constructor");が呼び出されました。次にBeetle()が呼び出され、暗黙のうちにsuper()(別名Insect())が呼び出されます。 iは9とjが、それは今jが39に設定され、フローはBeetle()で継続される0

デフォルトのint型の値を持つ意味し、その時点で初期化されていないので、これはi = 9, j = 0を印刷します。これで、ケースkBeetleのフィールドが初期化されます。したがって、Beetle()の明示的なコードになると、kはスーパーコンストラクタによって47とjから39に初期化されます。次のように

+0

メンバ(プリミティブと参照)が初期化されます 4.基底クラスのコンストラクタが呼び出されます 5.派生クラスの非静的メンバーは初期化されます 6.最後に、オブジェクトを作成するために必要なものがすべてあるので、派生クラスのコンストラクタが呼び出されます。 私は正しいですか? –

+1

@HelloLiliこの単純なケースでははいですが、私は原則としてそれを使用することに注意します。 Javaは、Java言語仕様で定義された一連の規則によって動作します。私は、あなたが特定の行動がどのように誘発されるかを学ぶことで、より良いと思う。 「静的メンバー」の代わりに、「静的メンバーの初期化をトリガーするクラスの読み込み」などを覚えておいてください。 –

2

これは説明することができる -

静的メンバは、非インスタンスメンバーがメンバーの唯一のコピーがクラスのすべてのインスタンス間で共有されるすなわちされているので、これらの部材が最初に初期化されます。

この場合、メインメソッドが存在するクラスの基底クラスに静的メンバーが存在するため、x1が最初に初期化されます。

したがって、最初のx1はに初期化されます。

サブクラスの静的メンバーx2は、同じ理由で続き、また昆虫クラスには他の静的メンバーが存在しないために続きます。

ビートルコンストラクタラインは、メインメソッドから印刷されます。あなたがその主な静的メソッドを呼び出したときに明白な理由

2

JVM(クラスローダ)用

スーパークラスとサブクラスのコンストラクタが次々と呼ばれているが、ビートルクラスをロードします。クラスローディングの後、クラスのすべての静的メンバーを初期化することを意味するビートルクラスの初期化が行われます。

基本クラスは常に暗黙的に初期化されるため、x1がx2より前に初期化されていることがわかります。

x1とx2の後に "Beetle constructor"が表示されます。これは、クラスの静的メソッドを参照するとき(mainを呼び出して実行しているとき)、JVMの実行順序がクラス静的メンバーの初期化main()メソッドの実行を続ける前に。ビートルコンストラクタが参照されないよう実験として

、別のクラスにmainメソッドを削除してみてください、

public class Beetle1 { 
public static void main(String[] args) { 
     System.out.println("Beetle1 constructor"); 
    } 
} 

は今、クラスローダは、それをロードしていない、とあなたはBeetle1コンストラクタが印刷表示されます。基底クラスで 1.静的メンバが最初に初期化され、派生クラスで 2.静的メンバーは次の初期化され、 3.基本クラス非static:原則として、だから私が言うことができる、

関連する問題