与隐式构造器和构造函数链接相关的混淆

  • 本文关键字:链接 构造函数 构造器 java
  • 更新时间 :
  • 英文 :


根据构造函数链接基构造函数,应在创建派生类对象并将其分配给基类引用时调用基构造函数。 基类中没有默认构造函数,但有一个显式参数化构造函数,因此 java 编译器不提供默认构造函数。 如果没有语句"this(10(;"编译器会抱怨,但一旦添加它,编译器就可以了。为什么??
我的意思是为什么在添加"this(10(;"后不尝试调用基类默认构造函数。它应该执行一个超级调用,然后执行添加的语句。

class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
this(10);//default value
}
public Child(int a) {
super(a);
System.out.println(a);
}
}

Java 语言规范 (§12.5( 定义了创建新实例时发生的情况;我强调了你问题最重要的部分。

  1. 如果此构造函数以同一类中另一个构造函数的显式构造函数调用 (§8.8.7.1( 开头(使用 this(,则使用相同的五个步骤计算构造函数调用的参数和过程递归。如果该构造函数调用突然完成,则此过程出于同样的原因突然完成;否则,请继续执行步骤 5

  2. 此构造函数
  3. 不以同一类中另一个构造函数的显式构造函数调用开始(使用 this(。如果此构造函数用于 Object 以外的类,则此构造函数将从显式或隐式调用超类构造函数(使用 super(开始。使用相同的五个步骤评估超类构造函数调用递归的参数和过程。如果该构造函数调用突然完成,则此过程将出于同样的原因突然完成。否则,请继续执行步骤 4。

因此,关键点是:

第一个构造函数
  • 显式调用第二个构造函数,因此上述步骤 2 适用;执行第二个构造函数,然后跳过步骤 3。
  • 步骤 3 是调用超类构造函数
  • 的地方,因此这意味着当构造函数从同一类调用另一个构造函数时,它不会直接调用超类构造函数。
  • 但是,如果从第一个构造函数中删除this(10);,则第一个构造函数不会调用同一类的另一个构造函数,因此步骤 3 适用,并隐式调用超类构造函数。这会导致错误,因为没有可以隐式调用的超类构造函数(没有参数(。

仅当没有其他构造函数时,默认/隐式构造函数才存在。

加入

public Parent(int a) {
System.out.println(a); 
}

删除默认构造函数Parent

如果你想保留默认的构造函数,你可以自己编写,这样:

public Parent(){
}

以下构造函数

public Child(){
}

将自动替换为

public Child(){
super();
}

如果第一行中没有构造函数调用(this()super()(,则会发生此替换。

这样可以确保在任何情况下都调用超级构造函数。

如果超类中没有没有参数的构造函数(如果已将默认构造函数替换为参数化构造函数(,则替换将失败。

因为如果你不this()添加到构造函数Child()- 编译器将插入super()语句,因此期望Parent类中没有arg构造函数。

class Parent{
public Parent(int a) {
System.out.println(a);
}
}
class Child extends Parent{
public Child(){
// this(10);// Commenting this(10) as if it did not exist.
super() // inserted by compiler unless you put this() or super() yourself
}
public Child(int a) {
super(a);
System.out.println(a);
}
}

最新更新