web-dev-qa-db-ja.com

継承を伴う静的ブロックの動作

私はこのような静的ブロックを使おうとしています:

Base.Javaという基本クラスがあります

public class Base {

    static public int myVar;

}

そして派生クラスDerived.Java

public class Derived extends Base {

    static
    {
        Base.myVar = 10;
    }
}

私のmain関数は次のようになります。

public static void main(String[] args)  {
    System.out.println(Derived.myVar);
    System.out.println(Base.myVar);
}

これにより、出力が0 0として出力されますが、予想どおり10 0です。誰かがこの振る舞いを説明できますか?また、派生クラスで静的変数の値を設定したい場合、どうすればそれを実現できますか?

31
Asha

私が理解しているように。 Derivedプロパティは呼び出さない(myVarBaseに属し、Derivedには属さない)。また、JavaはDerivedから静的ブロックを実行していません。静的フィールドをDerivedに追加してアクセスすると、Javaはすべての静的ブロックを実行します。

class Base {

    static public int myVar;

}


class Derived extends Base {

    static public int myVar2;

    static
    {
        Base.myVar = 10;
    }
}


public class Main {
    public static void main( String[] args ) throws Exception {
        System.out.println(Derived.myVar2);
        System.out.println(Base.myVar);
    }
}

Java仕様から、クラスが初期化されたとき(および静的ブロックが実行されたとき):

12.4.1初期化が発生する場合クラスまたはインターフェイスタイプTは、次のいずれかが最初に発生する直前に初期化されます。

•Tはクラスであり、Tのインスタンスが作成されます。
•Tはクラスであり、Tによって宣言された静的メソッドが呼び出されます。
•Tによって宣言された静的フィールドが割り当てられます。
•Tによって宣言された静的フィールドが使用され、フィールドは定数変数ではありません(§4.12.4)。
•Tはトップレベルクラス(§7.6)であり、T(§8.1.3)内に字句的にネストされたassertステートメント(§14.10)が実行されます。

22

静的初期化子-クラスが初期化されるまで、ブロックは実行されません。 Java言語仕様 段落8.7(静的初期化子)および12.4.1(初期化が発生した場合)を参照してください。

クラスで宣言された静的初期化子は、クラスが初期化されるときに実行されます(§12.4.2)。クラス変数のフィールド初期化子(§8.3.2)と一緒に、静的初期化子を使用してクラスのクラス変数を初期化できます。

JLS12.4.1から直接出た同様の例を次に示します。

class Super {
  static int taxi = 1729;
}
class Sub extends Super {
  static { System.out.print("Sub "); }
}
class Test {
  public static void main(String[] args) {
    System.out.println(Sub.taxi);
  }
}

このプログラムは以下のみを印刷します。

1729

クラスSubが初期化されないため。 Sub.taxiへの参照は、クラスSuperで実際に宣言されたフィールドへの参照であり、クラスSubの初期化をトリガーしません。

6
esaj

myVarのコピーが1つあり、親クラスと子クラスの両方が同じものを共有します。子クラスが初期化されない限り。

1
BOSS

私たちがするとき

class Base {

    public static int myVar = 0;
    static {
        System.out.println("Base");
    }
}

class Derived extends Base {

    static {
        System.out.println("Derived");
        Base.myVar = 9;

    }
}

public class StaticBlock {

    public static void main(String[] args) {

        System.out.println(Base.myVar);
        System.out.println(Derived.myVar);
    }
}

出力はBase 0 0になります

これは、派生クラスの静的ブロックが実行されていないことを意味します。

0
januprasad

Java仕様-セクション8.7では、静的初期化子について説明しています。静的初期化子の機能と呼び出し順序について詳しく説明しています。 http:/ /docs.Oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7

0
Johnnie