2016-08-21 77 views
1

为什么this()需要在构造函数链的第一个语句中?为什么具有不同参数的多个`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)

为什么这需要成为第一个陈述?

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

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

+2

很好读这个http://stackoverflow.com/questions/1168345/why-does-this-and-super-have-to-be-the-first-statement-in-a-constructor?rq=1 –

+0

我在阅读相同类型的问题之前阅读了stackoverflow答案。我不明白这些答案 – ekaf

+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(),否则构造函数链将停留在循环。如果发生这种情况,编译器会给你一个错误。

0

每一个构造函数初始化类的一个实例。因此,在构造函数中,只能调用另一个构造函数。构造函数调用必须是第一个的原因是说你将一个实例的创建委托给另一个构造函数。否则,如果构造函数的第一行不是另一个构造函数的调用,那么实例在第一行执行之前已经实例化(即,隐式调用super())。因此,在调用构造函数之后就像是调用构造函数的第二时间内的一些构造,作为构造实例化一个实例只

0

为什么这()需要在构造函数链的第一个语句,这显然是非法的?:因为它是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语言中,构造器是特殊。如果你不能接受,你将不得不使用另一种语言。

相关问题