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.
Может кто-нибудь объяснить мне, почему это произошло?
Спасибо.
Ответы
Ответ 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
Ответ 4
Всякий раз, когда вы создаете экземпляр класса, переменные экземпляра сначала инициализируются, а затем выполняют конструктор
Ссылка: Являются ли поля инициализированными до того, как код конструктора запущен на Java?
Ответ 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();
, поэтому он будет выполняться перед вызовом конструктора.
Статический блок имеет первый приоритет, он выполняется во время загрузки класса.