Вопрос по java – Встроенные блоки инициализации в Java

4

У меня есть класс

public class MyMain{
    public static void main(String... arg){
            Temp t = new Temp(){
                {
                    System.out.println(" instance initialize");
                }
            };

        }
    }

class Temp{
    int i;

    {
        i=9;
        System.out.println("Static"+i);
    }
    Temp(){
        System.out.println("Temp const "+i);
    }
}

Когда я выполняю основной метод, вывод приходит:

Static9
Temp const 9
instance initialize

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

возможный дубликатJava initialization order issue, static vs instance fields Oliver Charlesworth
В качестве побочной точки, это не статично, где вы печатаете статично. Dave Newton

Ваш Ответ

7   ответов
0

прежде чем с ним можно что-либо сделать. Объект создается в памяти, и затем происходит печать вашей консоли.

15

subclass изTemp, Для каждого класса любые инициализаторы экземпляра выполняются перед телом конструктора, но суперкласс проходит инициализацию до инициализации подкласса. Итак, поток выполнения:

Initializers in Object Constructor body in Object Initializers in Temp Constructor body in Temp Initializers in anonymous class Constructor body in anonymous class (none)

Я бы настоятельно рекомендовал вам рефакторинг любого кода, который выглядел так или иначе - стремитесь к ясности, а не к хитрости.

Это то же самое поведение в C #?
@Gab: нет, не совсем. В C # инициализаторы переменных в производном классе выполняются перед конструктором в базовом классе.
2

base class анонимного класса, который вы создаете в данный момент и перед пустым неявным конструктором самого анонимного класса.

6

JLS 12.5 разъясняет порядок, в котором вещи происходят во время строительства (выделено мной):

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

(3) This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

(4) Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

(5) Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

Таким образом, конструкторы суперкласса (шаг 3) выполняются перед инициализаторами экземпляров (шаг 4). Оба выполняются до «остальной части тела этого конструктора» (чего у вас нет в вашем примере).

1

для ясности, у вас есть два инициализатора экземпляра: один в классе Temp и один в анонимном внутреннем классе, созданном в методе main (), который является подклассом Temp.

Пункт 2. Инициализаторы экземпляра фактически не работаютbefore Конструкторы.Согласно JLS, они запускаютсяduring a constructorпосле делегирования суперструктору и перед инициализацией полей экземпляра и завершением конструктора.

Пункт 3: в вашем коде каждый инициализатор корректно выполняется в соответствующее время. Я думаю, что вы ожидаете, что второй будет выполняться одновременно с первым, но это было бы неправильно, поскольку, как указано в пункте 1, они инициализируют два разных класса.

Пункт 4: Вы также можете быть запутаны между статическимиинициализаторы и инициализаторы экземпляров, Они две разные вещи.

2

Temp экземпляр класса, но экземпляр некоторого анонимного класса, который наследуется отTemp.

Таким образом, сначалаTemp инициализаторы называются (анонимный блок внутриTemp и его construstor) и инициализаторы в анонимном классе называются впоследствии.

1

Temp t = new Temp(){
    {
        System.out.println(" instance initialize");
    }
};

Вы создаете объект анонимного класса, который расширяет класс Temp.

Создание объекта подкласса:

initialize block from Superclass
constructor of Superclass
initialize block from Subclass
constructor of Subclass

Похожие вопросы