web-dev-qa-db-ger.com

Verhalten von statischen Blöcken bei Vererbung

Ich versuche, statische Blöcke wie folgt zu verwenden:

Ich habe eine Basisklasse namens Base.Java

public class Base {

    static public int myVar;

}

Und eine abgeleitete Klasse Derived.Java:

public class Derived extends Base {

    static
    {
        Base.myVar = 10;
    }
}

Meine main Funktion ist wie folgt:

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

Dies druckt die Ausgabe als 0 0 aus, wo ich 10 0 erwartet habe. Kann jemand dieses Verhalten erklären? Wie kann ich das erreichen, wenn meine abgeleiteten Klassen die Werte für eine statische Variable festlegen sollen?

30
Asha

Wie ich es verstehe. Sie rufen keine Derived -Eigenschaften auf (myVar gehört zu Base, nicht zu Derived). Und Java führt keinen statischen Block von Derived aus. Wenn Sie Derived ein statisches Feld hinzufügen und darauf zugreifen, führt Java alle statischen Blöcke aus.

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);
    }
}

Aus der Java-Spezifikation, wenn die Klasse initialisiert wird (und der statische Block ausgeführt wurde):

12.4.1 Bei Initialisierung Eine Klasse oder ein Schnittstellentyp T wird unmittelbar vor dem ersten Auftreten einer der folgenden Aktionen initialisiert:

• T ist eine Klasse und eine Instanz von T wird erstellt.
• T ist eine Klasse und eine von T deklarierte statische Methode wird aufgerufen.
• Ein mit T deklariertes statisches Feld wird zugewiesen.
• Ein mit T deklariertes statisches Feld wird verwendet und das Feld ist keine konstante Variable (§4.12.4).
• T ist eine Klasse der obersten Ebene (§7.6), und eine in T (§8.1.3) lexikalisch verschachtelte Assert-Anweisung (§14.10) wird ausgeführt.

22

Statische Initialisierungsblöcke werden erst ausgeführt, wenn die Klasse initialisiert wurde. Siehe Java-Sprachspezifikation Absätze 8.7 (Statische Initialisierer) und 12.4.1 (Bei Initialisierung):

Ein in einer Klasse deklarierter statischer Initialisierer wird ausgeführt, wenn die Klasse initialisiert wird (§12.4.2). Zusammen mit Feldinitialisierern für Klassenvariablen (§8.3.2) können statische Initialisierer verwendet werden, um die Klassenvariablen der Klasse zu initialisieren.

Hier ist ein ähnliches Beispiel aus JLS 12.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);
  }
}

Dieses Programm druckt nur:

1729

weil die Klasse Sub niemals initialisiert wird; Der Verweis auf Sub.taxi ist ein Verweis auf ein tatsächlich in der Klasse Super deklariertes Feld und löst keine Initialisierung der Klasse Sub aus.

6
esaj

Es gibt eine einzige Kopie von myVar und sowohl die Eltern- als auch die Kinderklasse teilen sich die gleiche. Bis und sofern keine Kinderklasse initiiert wird.

1
BOSS

Wenn wir das tun

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);
    }
}

Die Ausgabe wird Base 0 0 sein

Das bedeutet, dass der statische Block der abgeleiteten Klasse nicht ausgeführt wird. !!

0
januprasad

Hier ist der Link zur Java-Spezifikation - Abschnitt 8.7 behandelt statische Initialisierer. Es gibt gute Details darüber, wie sie funktionieren sollen und in welcher Reihenfolge sie aufgerufen werden. http://docs.Oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7

0
Johnnie