在为我的决赛学习期间,我在我正在学习的书中看到了以下陈述。考虑以下代码:
class A {
public A(int x) { }
}
class B extends A {
public B(int x ) { }
}
是否必须在类B(super(x))的构造函数中调用类A的构造函数。该书指出它不是强制性的,因为它们具有确切数量和类型的参数。但是当我在java编译器中尝试这个时,会抛出以下错误:
A类中的构造函数A不能 适用于给定类型;需要: int found:没有参数原因: 实际和正式的参数列表 长度不同
答案 0 :(得分:17)
编译器会自动在开头插入super()
。
但是,即使构造函数参数super()
(不带参数)也会添加,它会调用超类的默认构造函数。你没有,因此错误。
您必须指定super(x)
(以调用A(x)
),或定义无参数构造函数。
顺便说一下,Eclipse编译器提供了一种更好的错误消息:
隐式超级构造函数A()未定义。必须显式调用另一个构造函数
答案 1 :(得分:4)
看起来编译器尝试使用super()
创建对超类默认构造函数的调用,这是不可用的:
required: int
found: no arguments
但回到你的书:我从来没有听说过如果实际的构造函数与直接超类中的构造函数具有完全相同的参数列表,则可以跳过构造函数中的super
语句。只隐式添加对超类的默认构造函数的调用(super()
),但这要求超类具有默认构造函数。
与书中所写的内容相反(或者与您对书面文字的理解相反),这里是语言规范中的一句话:
如果构造函数体不以显式构造函数调用开头 并且声明的构造函数不是原始类Object的一部分 编译器隐式假定构造函数体以super开头 类构造函数调用“super();”,调用其构造函数 不带参数的直接超类。
答案 2 :(得分:4)
如果您的基类具有默认构造函数(no-arg构造函数),则在扩展B
时,您无需显式调用super()
,因为它以任何方式调用。
但是当你有一个带参数的构造函数时,在使用B
中的参数构造构造函数时,你需要传递super()
A
的参数
示例:
class A {
public A(int x) { }
}
class B extends A {
public B(int x )
{
super(x); // need to specify the parameter for class A
//...
}
}
答案 3 :(得分:1)
如果您没有默认构造函数并且正在创建具有默认构造函数的实例,则会发生这种情况。因为如果你有任何参数化构造函数,那么编译器不会为你插入默认的构造函数,而是你必须定义。
答案 4 :(得分:0)
在Java的情况下调用超类的构造函数是必要的。因此,每当生成子类的构造函数时,超类的构造函数都是由IDE自己创建的。
这是因为每当基类构造函数需要参数时,编译器认为它们将由基类构造函数填充。如果是默认构造函数,则可以。无需在子类中调用super()。