2015-12-16 3 views
6
class DemoClass { 
    public static void main(String args[]) { 
     System.out.println("Start"); 
     A a=new D(); 
    } 
} 
class A { 
    static { 
     System.out.println("Static A"); 
     A c=new C(); 
    } 

    public A() { 
     System.out.println("Constr A"); 
    } 
} 

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

    public B() { 
     System.out.println("Constr B"); 
    } 
} 

class C extends B { 
    static { 
     System.out.println("Static C"); 
    } 

    public C() { 
     System.out.println("Constr C"); 
    } 
} 

class D extends C { 
    static { 
     System.out.println("Static D"); 
    } 

    public D() { 
     System.out.println("Constr D"); 
    } 
} 

Порядок исполнения для выше код:Когда статический блок будет выполнен в JAVA при создании объекта?

Start 
Static A 
Constr A 
Constr B 
Constr C 
Static B 
Static C 
Static D 
Constr A 
Constr B 
Constr C 
Constr D 

На мой взгляд, все статические блоки должны быть выполнены первым, то только объект будет создан. Но здесь сначала создается объект «A c = new C()» в статическом блоке класса A, а затем выполняются другие статические блоки. Зачем?

+3

Как в стороне, я подозреваю, что вы могли бы показали это с 3-х классов, или, возможно, только 2 так же, как легко - и сделал проще предоставить исчерпывающий список событий. –

ответ

13

Статический инициализатор всех классов имеет , запущенный, но для инициализации D инициализируется C, поэтому B должен быть инициализирован, поэтому A должен быть инициализирован. В момент выполнения кода в статическом инициализаторе в A все классы участвуют в состоянии «инициализируется».

В статическом инициализаторе A, он создает экземпляр C - но C является уже инициализации, поэтому инициализатор не начинается снова ... виртуальная машина просто отмечает, что это уже инициализирован (в пределах тот же поток) и продолжается.

Детали всего этого в JLS 12.4.2. В частности, пуля:

Если Class объект для C указывает на то, что инициализация для C с помощью текущего потока, то это должно быть рекурсивный запрос инициализации. Выпуск LC и завершите нормально.

и

Далее, если C является классом, а не интерфейс, а его суперкласс еще не был инициализирован, то пусть SC будет его суперкласс и пусть SI1, ..., SIN быть все суперинтерфейсы C, объявляющие хотя бы один метод по умолчанию. [...]

Для каждого S в списке [SC, SI1, ..., SIn] рекурсивно выполните всю эту процедуру для S. Если необходимо, сначала проверьте и подготовьте S.

... актуальны.

+0

Я озадачен «Constr B» перед «Static B». У вас есть предложение? – Mikey

+1

@Mikey: Это точно то же самое - это часть построения C, которая происходит, когда выполняется * body * статического инициализатора для A. –

-2

когда JVM начал в то время всех статические члены будут сканироваться и память будет выделены для них, то она будет идти не статичный ..

поэтому сначала он напечатает статическое то не статический

+0

Не думаю, что вы внимательно прочитали вопрос. –

5

@JonSkeet сказал все в технических терминах, и я не могу сказать больше этого. Позвольте мне попытаться объяснить с помощью аналогий:

Подумайте о статической инициализации, открывающей дверь комнаты и выполнение конструктора, как выполнение/отделка вещей в этой комнате.

Теперь, чтобы открыть дверь комнаты D, вам нужно открыть дверь C, для C вам нужно B, а для B вам нужно A. Теперь вы находитесь в комнате A, и у вас есть законченные двери, открывающие формальности в комнате A. И, закрывая формальности открытия двери в комнате A, вы видите примечание, которое завершает работу комнаты C (A c=new C();). Теперь, поскольку комната C и ее зависимые комнаты уже открыты, вам не нужно снова открывать (значит, не инициализация статического блока).Но прежде чем перейти к комнатным C закончат комнату открывающейся формальности т.е. System.out.println("Static A"); Так, в консоли у вас есть:

Статических

Теперь вы находитесь в комнате C, и вы должны закончить эта комната, но до этого вы закончите B и A из-за зависимости (C расширяет B и B расширяет A). Таким образом, в консоли у вас есть:

CONSTR CONSTR B CONSTR C

Теперь вы снова вернуться в комнату и увидеть дверь формальности открытия закончены. Таким образом, вы придете к комнате B, то C и затем D. Итак, в консоли у вас есть:

Статический B Статический C Статический D

Теперь вы заканчиваете работу в комнате D (A a=new D();), и для этого вам нужно закончить работу C, B и C из-за зависимости (D расширяет C, C расширяет B и B продолжается A). Таким образом, в консоли у вас есть:

Constr Constr B Constr C Constr D

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