2015-01-13 7 views
11

Il seguente codice Java non richiama l'inizializzatore statico della classe B. Perché?Inizializzatore statico non invocato per una classe derivata

Codice: uscita

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

Programma:

A static init 
f() called 

provata su JDK 1.8.0_25

+1

Forse un duplicato di http://stackoverflow.com/questions/13475172/java-static-initialization-with-itheritance – h7r

risposta

13

Non esiste una cosa come "costruttore statico". È un blocco di inizializzazione statico ed è eseguito solo quando la classe è inizializzata. Poiché si chiama un metodo statico di classe A (anche se ci si riferisce ad esso tramite la classe B), non è necessario inizializzare la classe B. Chiamare lo B.f(); equivale a chiamare A.f();.

Il blocco di inizializzazione statico di classe B sarà eseguito se si crea un'istanza di classe B o accedere un membro/metodo statico della classe B.

Qui sono gli unicicondizioni che attivano inizializzazione classe (JLS 12.4.1):

una classe o interfaccia tipo T viene inizializzato immediatamente prima del primo verificarsi di uno qualsiasi dei seguenti:

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. 
+0

Aggiunta: cosa succede se la classe B sostituisce f()? – Niels

+0

@Niels, non esiste una cosa che sovrascrive i metodi 'static'. Se esiste un metodo 'static'' f() 'in' B', verrà chiamato. –

+0

@Niels Non è possibile sovrascrivere un metodo statico. Se B definisse il proprio metodo statico 'f()', la classe B verrebbe caricata e il suo blocco di inizializzazione statico sarebbe eseguito, e quel metodo 'f()' è il metodo che verrebbe eseguito.In tal caso, verrà caricato anche A, poiché si tratta di una super classe di B. – Eran

5

Poiché solo classe A definisce il metodo f(), classe B è caricati ma non inizializzato.

È possibile utilizzare java -verbose:class MyClassName per verificare questo.

Su una macchina jdk6/jdk 8, verrà stampato.

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

Classe B verrà inizializzata pigramente ma caricato avidamente (dal momento che viene indicato).

Modificare il codice in A.f(). Quindi vedrai che B non è stato caricato.

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

Nota: Classe carico e inizializzazione sono 2 cose diverse. Consultare la documentazione per Class.forName() per i dettagli.

+0

Sai se B è garantito per essere caricato, o potrebbe dipendere dalla piattaforma? –

+1

@pbabcdefp - Sarà dipendente dalla VM (implementazione). Alcune implementazioni caricheranno avidamente 'B', altre potrebbero risolvere la chiamata a' A' direttamente, quindi non caricando 'B'. – TheLostMind

Problemi correlati