我在 scjp 指南中阅读如下
事实上,你不能不调用对象的实际类类型的构造函数,还要调用它的每个超类的构造函数来创建一个新对象!
例如
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
我没有创建 Person 实例,但它是合法的。
请为我解释一下,谢谢您的帮助。
我在 scjp 指南中阅读如下
事实上,你不能不调用对象的实际类类型的构造函数,还要调用它的每个超类的构造函数来创建一个新对象!
例如
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
我没有创建 Person 实例,但它是合法的。
请为我解释一下,谢谢您的帮助。
他们真正的意思是
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
编译器提供的 ie 将隐式调用super()
.
正如我们已经明确定义的那样Super(int num)
,我们将必须明确创建无参数构造函数,如下所示。
public Super(){
}
首先,您不必创建父实例 ( 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);
}
}
每当您实例化一个子类时,它都会首先调用您的超类的构造函数。
您可以在此处找到更多相关信息:JSL §8.8.7
人.java
public class Person {
public Person() {
System.out.println("Super class constructor called");
}
}
雇员.java
public class Employee extends Person {
public Employee() {
System.out.println("Sub class constructor called");
}
}
如果您随后实例化您的员工:
Employee e = new Employee();
输出:
超类构造函数调用
子类构造函数调用
超类的 nullary 构造函数被隐式调用。
这是因为构造函数链接:
默认情况下,任何构造函数中的第一条语句是super();(这是对超类默认构造函数的调用)。
我没有创建 Person 实例,但它是合法的:那是因为您在 Person 类中有一个默认构造函数。所以Employee类构造函数实际上可以调用超类构造函数。人()
最重要的是,您要在其中声明构造函数的当前类,直到基类的所有构造函数都应该可以通过 super() 访问。如果没有,您必须通过使用适当参数的 super 显式调用来显式地使它们可访问。
您遇到了 java 的一个奇怪之处。
如果您没有定义任何构造函数、默认值或“无参数”,则构造函数是隐式定义的。这就像看不见的代码。
如果您定义任何构造函数,args 或没有 args,隐式默认构造函数就会消失。
更复杂的是,任何子类构造函数的第一行必须是调用超类的构造函数。如果您没有显式调用一个,则隐式调用无参数构造函数。