为什么多个带有不同参数的`this()`在父构造函数中不起作用?

时间:2016-08-21 12:40:28

标签: java this constructor-chaining

为什么MyViewModel需要在构造函数链的第一个语句中?

为什么具有不同参数的多个this()在最终的构造函数中不起作用?

this()

为什么我不能在构造函数package thislatest; public class ThisLatest { public static void main(String[] args) { A a1= new A(10,20,30); a1.display(); } } class A { int x,b; static int c; A(){ System.out.println("constructor chaining1");} A(int y) { //this(); System.out.println("constructor chaining2"); b=y; } A(int x,int y) { // this(x); System.out.println("constructor chaining3"); x=x; x=y; } A(int x,int y,int c) { this(); this(y); this(x,y); x=x; //self reference initialised by previous constructor b=y; //no need of this keyword since name is different this.c=c; //current instance variable or A.c=c will also work } void display() { System.out.println(x+b); //wrong result due to self reference System.out.println(c+b); //correct reference } } 中使用多个this()

为什么这需要成为第一个声明?

只是为了保持语言流动吗?

我是初学者,请使用简单的术语:)

3 个答案:

答案 0 :(得分:1)

不允许在同一构造函数中调用多个构造函数,但允许链接它们以便一个调用另一个,依此类推。您可以这样做,直到您的类中的构造函数用完为止。考虑下面的课程:

public class MyClass() {
    public MyClass() {
        this(1);
        System.out.printf("Calling MyClass()%n");
    }

    public MyClass(int a) {
        this(a, 2);
        System.out.printf("Calling MyClass(%d)%n", a);
    }

    public MyClass(int a, int b) {
        System.out.printf("Calling MyClass(%d, %d)%n", a, b);
    }
}

以下客户端代码:

public class Client() {
    public static void main(String[] args) {
        new MyClass();
    }
}

如果您运行上面的代码,输出将是:

Calling MyClass(1, 2)
Calling MyClass(1)
Calling MyClass()

上面输出的顺序似乎是错误的顺序,因为printf()调用是在构造函数调用之后完成的。按照下面的箭头,您可以看到构造函数调用的开始位置以及最终结束的位置:

Object        MyClass               Client
------        -------               ------
              MyClass() <---------- main(String[])
                 |
                 V
              MyClass(int)
                 |
                 V
Object() <--- MyClass(int, int)

如果您想知道最后一个箭头的含义:所有Java类,包括MyClass,都秘密扩展Object - 类。 MyClass 中的最后一个构造函数实际上是:

    public MyClass(int a, int b) {
        super();
        System.out.printf("Calling MyClass(%d, %d)%n", a, b);
    }

您的类至少需要一个隐式或显式调用super()的构造函数,否则构造函数链将陷入循环。如果发生这种情况,编译器会给出错误。

答案 1 :(得分:0)

每个构造函数初始化一个类的单个实例。因此,在构造函数中,您只能调用另一个构造函数。构造函数调用必须是第一个的原因是,您将实例的创建委托给另一个构造函数。否则,如果构造函数的第一行不是另一个构造函数的调用,则在执行第一行之前已经实例化实例(即隐式调用super())。因此,之后调用构造函数就像是在构造函数中第二次调用一些构造函数,这显然是非法的,因为构造函数只实例化一个实例

答案 2 :(得分:0)

为什么this()需要在构造函数链的第一个语句中?:因为它是Java规范所要求的!例如,Python允许程序员在任何地方调用超类初始化方法。但Java不允许它。完全停止。

为什么带有不同参数的多个this()在最终的构造函数中不起作用?与上面相同的答案。询问为什么,只考虑如何是没用的,因为你不会改变语言规范。

让我们考虑一下如何。您可能有充分的理由将初始化方法称为构造函数的第一条指令。在这种情况下,只需使用非构造函数初始化方法,并从构造函数中调用这些方法:

class A {
    private void init1(int x) {
        // do something with x
    }

    private void init2(int x, int y) {
        // do something with x and y
        ...
        init1(x); // eventually call init1 in the middle of init2
        ...
    }

    A(int x) {
        y = 2 *x + 1;
        init2(x, y);    // call initialization method in the middle of ctor
    }
    A(int x,int y) {
        // eventually some instructions
        init2(x, y);
        // eventually other instructions
    }
}

在Java语言中,构造函数是特殊的。如果你不能接受,你将不得不使用另一种语言。