超类何时没有默认的构造函数? [英] When do superclasses not have a default constructor?

查看:137
本文介绍了超类何时没有默认的构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据关于构造函数的Java教程


您不必为类提供任何构造函数,但是
在执行此操作时必须小心。编译器会自动为任何没有构造函数的类提供
无参数的默认构造函数。
此默认构造函数将调用
超类的无参数构造函数。在这种情况下,如果
超类没有无参数构造函数,则编译器会抱怨,因此您必须验证
确实具有该参数。如果您的类没有显式超类,则它具有Object的
隐式超类,该类确实具有无参数的
构造函数。

如果您有没有显式默认构造函数的超类 A ,则

和一个子类 B 扩展了一个没有显式默认构造函数的A

If you have a superclass A that has no explicit default constructor,
and a subclass B extends A that has no explicit default constructor,

在驱动程序类的主方法中,您执行

A obj1 = new A();

a将创建默认构造函数,
它将调用对象类,对吗?

And in the main method of a driver class you do
A obj1 = new A();
a default constructor will be created,
which will call the default constructor of the Object class, correct?

但是如果您这样做

B obj2 = new B(); 按照教程的
,将生成B的默认构造函数,
,构造函数将调用超类的无参数构造函数,
依次调用该构造函数在对象中。

But if you do
B obj2 = new B();
according to the tutorial, a default constructor for B will be generated,
and the constructor will call the no-argument constructor of the superclass,
which will in turn call the constructor in Object.

那么超类何时将没有无参数构造函数?

So when will the superclass not have a no-argument constructor?

推荐答案

默认构造函数由编译器定义,当您不提供默认构造函数时。

The default constructor is defined by the compiler when you don't provide one.

因此,

public class A{}

将由编译器表示

public class A
  public A() {
    super(); //invokes Object's default constructor
  }
}

由于我对 A 没有定义显式构造函数。

Since my definition of A did not have an explicit constructor defined.

在上面的示例中, A 隐式扩展 Object ,而 Object的默认构造函数在编译器执行<$ c $时会自动调用c> super()。对于任何可能扩展 A 的类也是如此,例如:

In the example above A extends Object implicitly and Object's default constructor is automatically invoked by the compiler when it does super(). The same is true for any classes that may extend A, for example:

public class B extends A {}

将由编译器实现,类似于:

would be implemented by the compiler somewhat like:

public class B extends A {
   public B() {
      super(); //invokes A's default constructor
   }
}

如您所见将最终链接 Object 的默认构造函数,然后链接 A 的默认构造函数,最后是 B 的默认构造函数。

Which as you can see will end up chaining Object's default constructor, then A's default constructor and finally B's default constructor.

>那么,超类何时将没有无参数构造函数?

当您明确定义一个时,它将没有no-arg构造函数。例如,如果我将 A 的定义更改为

It won't have a no-arg constructor when you define one explicitly. For example, if I changed my definition of A to

public class A {
   public A(String name){}
}

然后 A 不再具有默认构造函数,我再也不能这样做

Then A no longer has a default constructor and I can no longer do this

public class B extends A {
   //Uh oh, compiler error. 
   //Which parent class constructor should the compiler call?
} 

现在 B 必须通过显式说明要使用的构造函数,从其父类显式链接正确的构造函数。例如

Now B must explicitly chain the right constructor from its parent class by explicitly stating which one to use. For example

public class B extends A {
   B() {
     super("B"); //Now the compiler knows which constructor to invoke
   }
}

Java Decompiler演示

实际上,您可以使用JDK附带的工具来演示所有这些内容。您的JDK bin目录中有一个名为 javap 的程序。这是Java Decompiler工具,可让您查看由编译器生成的代码。

You can in fact demonstrate all of this by using a tool that comes with your JDK. There is a program in your JDK bin directory called javap. This is the Java Decompiler tool, which lets you take a look at code generated by the compiler.

您可以编译我的示例,然后对它们进行反编译以查看生成的代码。 ,例如

You could compile my examples and then decompile them to look at the generated code, e.g.

javac A.java
javap A

反编译器会向您显示:

public class A {
  A();
}

其中清楚地显示了编译器添加了默认构造函数。

Which clearly shows the compiler added a default constructor.

您可以反汇编该类以查看字节码。

You may disassemble the class to see the byte codes.

javac B.java
javap -c B

它将显示如何调用父类的默认构造函数

And it will show how it invokes the parent class default constructor

class B extends A {
  B();
    Code:
       0: aload_0
       1: invokespecial #1 // Method A."<init>":()V
       4: return
}

如果我向 A 添加默认参数的构造函数,您将看到编译器不再提供默认的构造函数,而只提供了我明确定义的构造函数:

If I add a default parameter to the A's constructor, you will see the compiler no longer provides the default constructor, it just provides the one I defined explicitly:

class A {
    A(String name){}
}

然后我可以做

javac A.java
javap A

它产生

class A {
  A(java.lang.String);
}

这表明您在原始问题中引用的规范中所读内容是是的。

Which demonstrates that what you read in the specification you cited in the original question is true.

这篇关于超类何时没有默认的构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆