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