为什么我不能在构造函数中调用非静态方法作为此参数



有效代码1:

class ClassForTest{
    ClassForTest(int k){         
    };
    ClassForTest(){
         this(2);
         method();
    };
    int method(){return 1;}     
}

我的解决方案-我可以在构造函数中调用非静态方法!

无效代码

class ClassForTest{
    ClassForTest(int k){
    };
    ClassForTest(){
         this(method());
    };
    int method(){return 1;}
}

编译错误:

java: cannot reference this before supertype constructor has been called

有效代码2:

class ClassForTest{
    ClassForTest(int k){
    };
    ClassForTest(){
         this(method());  
    };
    static int method(){return 1;}
}

有效代码3:

class ClassForTest{
    ClassForTest(int k){
    };
    {
        method();
    }
    ClassForTest(){
         this(1);
    };
    int method(){return 1;}
}

这个行为集对我来说很奇怪。

你能共同解释一下吗?

更新

据我所知,编译器合并init块如下:

constructor(){
   super();
   nonStaticInitBlock;
   remain constructor code;
}

我看不出为什么我不能使用这个调用作为构造函数的参数有矛盾

编辑

实例初始值设定项在最后一次构造函数调用后调用。–Sotirios Delimanolis六月1日17:17

@Sotirios你错了

研究这个代码:

public class Order {
    { 
        System.out.println("initializer!");
    } 
    Order(){ 
        System.out.println("constructor");
    } 
    public static void main(String [] args){
        new Order(); 
    }
}

结果:

initializer!
constructor

(由于之前的答案不正确而更改(

我相信答案在于编译器给你的错误:

java: cannot reference this before supertype constructor has been called
                                   ^^^^^^^^^

查看JLS第12.5节:

如果该构造函数以同一类中另一个构造函数的显式构造函数调用(§8.8.7.1(开始(使用this(,则评估参数并使用这五个步骤递归处理该构造函数调用。

在JLS 8.8.7:中

构造函数体中的显式构造函数调用语句不能引用该类或任何超类中声明的任何实例变量、实例方法或内部类,也不能在任何表达式中使用this或super;否则,将发生编译时错误。

因此,为了运行第二个清单中的代码,在进入this()的主体之前,需要对method()进行求值。然而,规范禁止这样做,因为对象的状态可能尚未完全初始化,例如,对于类型的子类,其构造函数设置了该子类继承的某些状态。

class ClassForTest{
    ClassForTest(int k){
    };
    ClassForTest(){
         this(method());
    };
    int method(){return 1;}
}

现在method()是一个实例方法,这意味着它需要在ClassForTest类型的对象上调用。上述代码本质上意味着

ClassForTest(){
             this(this.method());
        };

并且不能在构造函数中调用this.something((,因为只有调用了超类的所有构造函数之后才会创建Object。所以这是不允许的。

其中,在静态方法的情况下,您不必等到对象创建,即调用所有超类构造函数。所以这是允许的。

最新更新