Не создавайте экземпляр superclass в конструкторе подкласса, но полностью легальный
Я прочитал в руководстве scjp как следующее
Фактически, вы не можете создать новый объект, не вызвав не только конструктор фактического типа класса объекта, но и конструктор каждого из его суперклассов!
Например
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
Я не создаю экземпляр Person, но это законно.
Пожалуйста, объясните мне, спасибо за вашу помощь.
6 ответов
Всякий раз, когда вы создаете экземпляр подкласса, он сначала вызывает конструктор вашего суперкласса.
Вы можете найти больше об этом здесь: JSL §8.8.7
Person.java
public class Person {
public Person() {
System.out.println("Super class constructor called");
}
}
Employee.java
public class Employee extends Person {
public Employee() {
System.out.println("Sub class constructor called");
}
}
Если вы затем создадите экземпляр своего сотрудника:
Employee e = new Employee();
Выход:
Конструктор суперкласса называется
Подкласс конструктор называется
Во-первых, вам не нужно создавать родительский экземпляр (Parent
) создать экземпляр дочернего класса (Employee
). Вы, должно быть, поняли неправильно.
Вызов конструктора родительского класса не означает создание нового родительского объекта экземпляра (вы не вызываете его с помощью new
поэтому новый экземпляр не создается). Вы создаете дочерний экземпляр, и для этого вам нужно сначала вызвать конструктор родителя из-за наследования. Представьте себе, например, родительский класс имеет private
поля, которые должны быть инициализированы в конструкторе (например, private final
поля). К этим полям нельзя получить доступ из дочернего класса, но они могут быть инициализированы из конструктора родительского класса. Вам нужно инициализировать эти поля в дочернем экземпляре, и единственный способ - это вызвать super()
,
В этом случае Person
имеет конструктор по умолчанию, который вызывается по умолчанию, нет необходимости явно вызывать его.
Но в случае Person
не имеет конструктора по умолчанию, вам нужно вызывать его явно. Например:
public class Person{
private final String name;
public Person(final String name) {
this.name = name;
}
}
public class Employee extends Person {
public Employee() {
}
}
Это не скомпилируется. Вам нужно изменить Employee
так это называет Person
конструктор явно. Например:
public class Employee extends Person {
public Employee(final String name) {
super(name);
}
}
Что они на самом деле имеют в виду
- Когда вы создаете объект подкласса, то есть вызывается его конструктор, тогда конструктор суперкласса вызывается internall
- Это потому, что для конструктора по умолчанию без аргументов
super()
вызовите конструктор суперкласса. - Это продолжается как иерархия классов, пока
Object
учебный класс.
Фактически, если вы не пишете конструктор без аргументов в суперклассе, то объявление подкласса вызовет ошибку компилятора.
public class Super {
public Super(int num){
}
}
public class Sub extends Super {
}
Здесь класс Sub
не скомпилируется с ошибкой Implicit super constructor Super() is undefined for default constructor
потому что он не может найти конструктор без аргументов в суперклассе как default no-argument constructor
т.е. предоставленный компилятором будет иметь неявный вызов super()
,
- Компилятор обеспечивает конструктор по умолчанию без аргумента, только если не определен другой конструктор
Как мы явно определили
Super(int num)
нам нужно будет явно создать конструктор без аргументов следующим образом.public Super(){ }
Это из-за цепочки конструктора:
Первым оператором внутри любого конструктора по умолчанию является super (); (Это вызов конструктора по умолчанию суперкласса).
Я не создаю экземпляр Person, но это допустимо, потому что у вас есть конструктор по умолчанию в классе Person. Таким образом, конструктор класса Employee может фактически вызвать конструктор суперкласса. Человек()
В итоге, текущий класс, в котором вы объявляете конструктор, весь конструктор до базового класса должен быть доступен через super(). Если нет, вы должны явно сделать их доступными, явно сделав вызов через super с соответствующими параметрами.
Вы столкнулись с одной из странностей Java.
Если вы не определяете никаких конструкторов, по умолчанию или "без аргументов", конструктор определяется неявно. Это как невидимый код.
Если вы определяете какой-либо конструктор с аргументами или без аргументов, неявный конструктор по умолчанию исчезает.
Чтобы еще больше разгадать тайну, первая строка любого конструктора подкласса должна вызывать конструктор суперкласса. Если вы явно не вызываете его, конструктор no-args вызывается неявно.