2015-01-13 15 views
11

Der folgende Java-Code ruft nicht den statischen Initialisierer der Klasse B auf. Warum?Statischer Initialisierer, der für eine abgeleitete Klasse nicht aufgerufen wird

Code:

class A 
{ 
    static 
    { 
     System.out.println("A static init"); 
    } 

    public static void f() 
    { 
     System.out.println("f() called"); 
    } 
} 

class B extends A 
{ 
    static 
    { 
     System.out.println("B static init"); 
    } 
} 

public class App 
{ 
    public static void main(String[] args) 
    { 
     B.f(); //invokestatic #16     // Method com/db/test/B.f:()V 
    } 
} 

Ausgabeprogramm:

A static init 
f() called 

auf JDK 1.8.0_25 Getestet

+1

Möglicherweise ein Duplikat von http://stackoverflow.com/questions/13475172/java-static-initialization-with-inheritance – h7r

Antwort

13

Es gibt nicht so etwas wie "statischen Konstruktor". Es ist ein statischer Initialisierungsblock und wird nur ausgeführt, wenn die Klasse initialisiert wird. Da Sie eine statische Methode der Klasse A aufrufen (obwohl Sie über die Klasse B darauf verweisen), muss die Klasse B nicht initialisiert werden. Der Aufruf von B.f(); entspricht dem Aufruf von A.f();.

Der statische Initialisierungsblock der Klasse B ausgeführt wird, wenn eine Instanz der Klasse B erstellen oder ein statisches Element/Methode B. Klasse

Hier sind die nur Bedingungen, die Klasse zugreifen Initialisierung (JLS 12.4.1 triggern):

T is a class and an instance of T is created. 

T is a class and a static method declared by T is invoked. 

A static field declared by T is assigned. 

A static field declared by T is used and the field is not a constant variable (§4.12.4). 

T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed. 
:

A-Klasse oder Schnittstelle Typ T unmittelbar vor dem ersten Auftreten irgendeinen der folgenden initialisiert wird

+0

Addition: was passiert, wenn Klasse B überschreibt f()? – Niels

+0

@Niels, es gibt kein Überschreiben von 'statischen' Methoden. Wenn es eine 'statische' Methode' f() 'in' B' gibt, wird diese aufgerufen. –

+0

@Niels Sie können eine statische Methode nicht überschreiben. Wenn B eine eigene statische 'f()' Methode definieren würde, würde Klasse B geladen und ihr statischer Initialisierungsblock würde ausgeführt, und diese 'f()' Methode ist die Methode, die ausgeführt würde.In diesem Fall würde auch A geladen werden, da es eine Superklasse von B ist. – Eran

5

Da nur Klasse A die Methode f() definiert, Klasse B ist geladen, aber nicht initialisiert.

Sie könnten java -verbose:class MyClassName verwenden, um dies zu überprüfen.

Auf einer jdk6/jdk 8-Maschine wird dies gedruckt.

[Loaded App from file:/C:/XXXX/] 
[Loaded A from file:/C:/XXXXXX] 
[Loaded B from file://C:/XXXXXXX] 
A static init 
f() called 

Klasse B wird lazily initialisiert werden, sondern geladen Gierig (da es genannt wird).

Ändern Sie Ihren Code in A.f(). Dann werden Sie sehen, dass B nicht geladen ist.

[Loaded App from file:/C:/XXXX/] 
[Loaded A from file:/C:/XXXXX] 
A static init 
f() called 

Hinweis: Klasse Laden und Initialisierung sind zwei verschiedene Dinge. Weitere Informationen finden Sie in der Dokumentation für Class.forName().

+0

Wissen Sie, ob B garantiert geladen wird oder ob es plattformabhängig ist? –

+1

@pbabcdefp - Es wird VM (Implementierung) abhängig sein. Einige Implementierungen werden "B" gierig laden, andere können den Aufruf von "A" direkt auflösen und somit nicht "B" laden. – TheLostMind

Verwandte Themen