Подтвердить что ты не робот

Java - метод, выполненный до конструктора по умолчанию

Я изучаю Java, и случайно наткнулся на следующий код, где по умолчанию выполняется конструктор по умолчанию.

public class ChkCons {

    int var = getVal();

    ChkCons() {
        System.out.println("I'm Default Constructor.");
    }

    public int getVal() {
        System.out.println("I'm in Method.");
        return 10;
    }

    public static void main(String[] args) {

        ChkCons c = new ChkCons();

    }

}

OUTPUT:

I'm in Method.
I'm Default Constructor.

Может кто-нибудь объяснить мне, почему это произошло?

Спасибо.

4b9b3361

Ответ 1

Выражения инициализации переменной экземпляра, такие как int var = getVal();, оцениваются после выполнения конструктора суперкласса, но до выполнения текущего тела конструктора класса.

Поэтому getVal() вызывается перед выполнением тела конструктора ChkCons.

Ответ 2

Конструктор вызывается до метода. Выполнение метода происходит после того, что является частью создания объекта, в котором вычисляются переменные экземпляра. Это может быть лучше понято из следующего кода.

class SuperClass{
    SuperClass(){
        System.out.println("Super constructor");
    }
}
public class ChkCons extends SuperClass{

    int var = getVal();

    ChkCons() {
        System.out.println("I'm Default Constructor.");
    }

    public int getVal() {
        System.out.println("I'm in Method.");
        return 10;
    }

    public static void main(String[] args) {

        ChkCons c = new ChkCons();

    }

}

Приведенный выше код имеет следующий вывод

Super constructor
I'm in Method.
I'm Default Constructor.

Здесь компилятор автоматически добавляет super(); в качестве первого оператора в конструкторе ChkCons(), и, следовательно, он вызывается до метода getVal().

Ответ 3

Мы можем ссылаться на следующую документацию о оракуле по инициализации переменных экземпляра (Emphasis is mine):

Инициализация членов экземпляра

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

Блоки инициализатора для переменных экземпляра выглядят так же, как статические инициализаторы, но без ключевого слова static:

{     // нужен какой-либо код для инициализации}

> Компилятор Java копирует блоки инициализации в каждый конструктор. Поэтому этот подход может использоваться для обмена блоком кода между несколько конструкторов.

Окончательный метод нельзя переопределить в подклассе. Это обсуждается в уроке о интерфейсах и наследовании. Вот пример используя последний метод инициализации переменной экземпляра:

class Whatever {
private varType myVar = initializeInstanceVariable();

protected final varType initializeInstanceVariable() {

    // initialization code goes here
} 
}

https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

Ответ 5

public class InitializerIndex {

    public InitializerIndex() {
        // TODO Auto-generated constructor stub
        System.out.println("Default Constructor");
    }

    static {

        System.out.println("Static Block one");
    }

    {
        System.out.println("Init one");
    }

    void letsRoll() {

    }

    public static void main(String[] args) {
        new InitializerIndex().letsRoll();
        new InitializerIndex().letsRoll();
    }

    {
        System.out.println("Init Two");
    }

    static {
        System.out.println("Static Block two");
    }

}

Будет иметь следующий вывод:

Static Block one
Static Block two
Init one
Init Two
Default Constructor
Init one
Init Two
Default Constructor

Сначала загружается статический контент, а затем содержимое экземпляра. Статический контент загружается только один раз.

Даже когда создаются два объекта, статический блок вызывается только при создании первого объекта.

Кроме того, во время создания объекта или в конструкторах, если вы хотите использовать такие методы, как этот

 int var = getVal();

Вы должны использовать статические методы.

Ответ 6

Это потому, что вы инициализируете метод в поле с помощью int var = getVal();, поэтому он будет выполняться перед вызовом конструктора. Статический блок имеет первый приоритет, он выполняется во время загрузки класса.