在构造函数中调用 this() 是否会隐式调用 super()?

Is it true that calling this() inside a constructor implicitly calls super()?

我试图理解

为什么this()和super()不能一起使用?

我在这里阅读了很多关于Whosebug的相关讨论,并且理解了很多东西。但我仍然有一个困惑是。

calling this() inside a constructor implicitly calls super()

考虑这段代码..

class Top
{
    int z;
    Top()
    {
        System.out.println("Top default constructor");
    }

}
class A extends Top
{
    int x;
    A(int num)
    {
        x=num;
        System.out.println("A parameterized constructor");
    }
    A()
    {
        this(5);
        System.out.println("A default constructor");
    }
    public static void main(String arg[])
    {
        new A();
    }
}

并且输出是:

Top default constructor

A parametrized constructor

A default constructor

我没想到输出的第一行“Top default constructor”因为没有 super() 调用,隐式或显式。

所以我可能误解了一些东西。请解释。

在构造函数内部调用 this() 会调用同一 class 的另一个构造函数。另一个构造函数会调用 super() 构造函数(隐式或显式),这就是为什么不能在同一个构造函数中同时调用 this()super() 的原因,因为那样会导致两个 super() 正在调用构造函数。

请注意,每当我写 this()super() 时,我并不一定意味着调用无参数构造函数(除了对 super() 的隐式调用总是super class 的无参数构造函数,正如 Joeblade 所评论的那样)。两个调用都可以有参数。

在您的代码示例中,A() 构造函数调用 A(int) 构造函数(这就是 this(5) 所做的),后者隐式调用 Top()(无参数)构造函数。

this(5) 调用 A(int num) 隐式调用 super()

Is it true that calling this() inside a constructor implicitly calls super()?

在构造函数中调用 this() 将调用 class 的零参数构造函数。如果 class 的零参数构造函数没有显式调用 super(...),那么是的,将会有一个 implicit 调用零参数args super() 构造函数。如果您的 class 中的零参数构造函数显式调用了其他 super 签名,那么当然已经完成了。

对于一般的构造函数来说都是如此。在您的 A class 中,由于您的 A(int) 构造函数没有对 this() super() 的任何调用,隐式 super() 完成。

I was not expecting the first line in output "Top default constructor" as there is no super() call,implicit or explicit.

是的,有一个隐含的。 :-)

基本规则是这样的:Some base class constructor must be 运行 prior to code in the derived class 运行宁。这就是为什么调用 this(...)super(...) 必须是构造函数中 first 的原因。如果构造函数没有对 super(...) 的显式调用,总会有对 super() 的隐式调用(没有参数)。

这在 Creation of New Class Instances 的 Java 语言规范部分进行了解释,重点是用粗体标记的超类构造函数:

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

因此,在您的情况下,当使用 this(5) 调用构造函数 A(int num) 时,第 3 步表明它隐式调用超类构造函数,递归地应用相同的过程。

请注意,您可以通过调试构造函数调用的顺序来跟进该过程。