2014-02-01 2 views
-1

Я нашел этот пример, и я хочу понять его логику? как конструкторы и статические блоки и блоки инициализатора работают в наследовании? на какой стадии называется каждый?статический блок против блока инициализатора против конструктора в наследовании

public class Parent { 

    static { 
     System.out.println("i am Parent 3"); 
    } 

    { 
     System.out.println("i am parent 2"); 
    } 

    public Parent() { 
     System.out.println("i am parent 1"); 
    } 

} 

public class Son extends Parent { 

    static {System.out.println("i am son 3");} 
    {System.out.println("i am son 2");} 

    public Son() { 
     System.out.println("i am son 1"); 
    } 

    public static void main(String[] args) { 
     new Son(); 
    } 
} 

выход:

i am Parent 3 
i am son 3 
i am parent 2 
i am parent 1 
i am son 2 
i am son 1 
+5

Вы уже подали ответ на свой вопрос. – jax

+3

Вместо использования чисел используйте собственные имена, такие как статический блок, блок инициализатора, конструктор, чтобы сделать вывод более четким. – Pshemo

ответ

9

Статический блок вызывается один раз, когда класс загружается и инициализируется JVM. Инициализатор экземпляра выполняется, когда экземпляр класса создается, как и конструктор.

Статические и экземпляра инициализаторы описаны в статическом блоке Java Language Specification

+1

И, очевидно, он вызывается перед конструктором. – apnorton

+0

@anorton Класс должен быть инициализирован до того, как он будет создан. – EJP

1

запускается на выполнение, когда класс загружается в JVM, тогда как конструктор блок запускается на выполнение при создании экземпляра.

Статический инициализатор является эквивалентом конструктора в статическом контексте. Вы, конечно, увидите это чаще, чем инициализатор экземпляра.

2

Статический блок вызывается, когда ваш класс будет загружен и ваш класс первым загружается загрузчиком классов в JVM поэтому сначала они получают казнены

затем создать объект таким образом ваш родительский инициализации вызывается блок, то ваш родительский конструктор из-конструктора цепочки в Java, то полученный блок инициализации класса, то производного класса конструктор

7

вы должны знать, что

  1. первая инструкция в конструкторе вызова конструктора родительского класса super(params) или если вы хотите использовать конструктор по умолчанию super(). В случае конструктора по умолчанию вам не нужно писать его явно.
  2. код в инициализаторе блоке перемещаются в конструктор сразу после super(...) вызова
  3. статического блок выполняется при инициализации класса, который выполняется после того, как он полностью загружен (с его родительскими классами) по виртуальной машине Java.

Так классы скомпилированы в классы, подобные этому.

public class Parent { 
    static { 
     System.out.println("Parent static block"); 
    } 

    public Parent() { 
     super(); 
     { 
      System.out.println("Parent initializer block"); 
     } 
     System.out.println("Parent constructor"); 
    } 

} 

public class Son extends Parent { 

    static { 
     System.out.println("Son static block"); 
    } 

    public Son() { 
     super(); 
     { 
      System.out.println("Son initializer block"); 
     } 
     System.out.println("Son constructor"); 
    } 

    public static void main(String[] args) { 
     new Son(); 
    } 
} 

Чтобы быть в состоянии выполнить main метод из класса Son нуждается в JVM нагрузки кода этого класса (и классы расширяющим его). После того, как класс полностью загружен JVM инициализирует его статическое содержимое, которое включает в себя выполнение статических блоков (да, в одном классе может быть более одного статического блока). Чтобы полностью загрузить Son класс JVM должен знать сведения о своем родительском классе, чтобы он полностью загрузил класс Parent до Son, что означает, что он также выполнит свои статические блоки перед статическими блоками в классе Son.

Так выход будет выглядеть следующим образом:

  • Parent static block
  • Son static block

Сейчас в main методе вы вызываете Son конструктор класса через new Son() который код выглядит как

super(); 
{ 
    System.out.println("Son initializer block"); 
} 
System.out.println("Son constructor"); 

С момента своего super() см Parent конструктор класса, который

super();// this will invoke Object constructor since Parent 
     // doesn't extend anything (which means it extends Object class) 
{ 
    System.out.println("Parent initializer block"); 
} 
System.out.println("Parent constructor"); 

как результат вы увидите

  • Parent initializer block
  • Parent constructor

Это ручки Parent#constructor() выполнена с super() так рядом ты будешь см код от Son конструкторы после super(), который будет генерировать

  • Son initializer block
  • Son constructor

Чтобы увидеть, что классы будут загружены даже прежде чем использовать Son конструктор или даже main метода вы можете просто распечатать что-то перед использованием Son конструктор, подобный

System.out.println("ABC      // before new Son()"); 
new Son(); 

, что приведет к

Parent static block 
Son static block 
ABC      // before new Son() 
Parent initializer block 
Parent constructor 
Son initializer block 
Son constructor 
+0

Об этом пока нет. Сначала запускается статический инициализатор и один раз, когда класс загружается и инициализируется первым, что может занять несколько часов или недель до вызова любого конструктора. Вы не поняли этого. – EJP

+0

@EJP Вы правы, удалили его. – Pshemo

+0

Я не просто комментирую эти три слова. Вы вообще не отделили загрузку и инициализацию класса от строительства. – EJP

Смежные вопросы