1

为什么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()在构造函数中使用多个A(int x,int y,int c)

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

只是为了保持语言的流畅吗?

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

4

3 回答 3

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-class。最后一个构造函数MyClass 实际上如下所示:

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

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

于 2016-08-21T14:50:17.010 回答
0

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

于 2016-08-21T13:52:59.173 回答
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 语言中,构造函数是特殊的。如果您不能接受,您将不得不使用另一种语言。

于 2016-08-21T14:01:08.313 回答