Вопрос по порядку вызова конструктора базового класса
class B {
private B() {
System.out.println("No args constructor B");
}
protected B(String str) {
System.out.println("Constructor with string B");
}
}
class A extends B {
public A() {
this("some string");
System.out.println("No args constructor A");
}
public A(String str) {
super(str);
System.out.println("Constructor with string A");
}
}
public class Main {
public static void main(String[] args) {
B b = new A();
}
}
На просторах интернета не нашел точного ответа на вопрос. Прошу подсказать, верно ли я понимаю порядок вызова конструктора базового класса: Если в конструкторе потомке (Конструктор1) первой строкой вызвать другой конструктор потомка (Конструктор2), то вызов конструктора базового класса из Конструктора1 произведен не будет, вместо этого управление будет передано сразу в конструктор 2 и уже там, если нет вызова другого конструктора потомка, будет вызван конструктор базового класса. Я правильно понимаю логику инициализации?
Ответы (2 шт):
при инициализации объекта, компилятор вызовет сначала дефолтный конструктор(который без аргументов), он неявно создаётся во всех классах, если его не переопределить.
если у класса есть "родитель", то по средствам ключевого слова super() будет вызываться конструктор "родителя" потом его "родителя" и тд до самого верха, пока не вызовется конструктор класса Object от которого в java наследуются все классы.
если написать следующее
public class Main extends Object{
}
ide напишет Class 'Main' explicitly extends 'java.lang.Object'
типо зачем ты мне это пишешь, я и так знаю что всё наследуется от Object
если написать так
class Class1{
public Class1() {
System.out.println("class1");
}
}
class Class2 extends Class1{
public Class2() {
System.out.println("class2");
}
}
class Class3 extends Class2{
public Class3() {
System.out.println("class3");
}
}
public class Main {
public static void main(String[] args) {
Class3 class3 = new Class3();
}
}
то вывод будет следующий
class1
class2
class3
получается своего рода лесенка, перед тем как создать обьект, сначала вызовется конструктор родительского класса, потом его родителя и тд, пока не дойдёт до главного папы(Object), а далее будут вызывается конструкторы по "лесенке" вниз.
Если бы вы запустили код в своём вопросе, вы бы увидели следующий вывод:
Constructor with string B
Constructor with string A
No args constructor A
То есть ваше понимание логики инициализации вполне корректно:
- При вызове конструктора без параметров
new A()происходит вызов перегруженного конструктораA(String str) - При вызове перегруженного конструктора
A(String str)происходит вызов аналогичного конструктора базового классаprotected B(String str). Вызов дефолтного конструктора базового класса в данном случае невозможен (например, при помощиsuper();), так как он определён как приватный! - Завершается перегруженный конструктор базового класса, код возвращается в перегруженный конструктор потомка.
- Завершается перегруженный конструктор потомка, код возвращается в конструктор без параметров потомка.