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

时间:2014-06-01 16:29:05

标签: java methods constructor instance

有效代码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;
}

我没有看到矛盾,为什么我不能使用这个invokation作为构造函数的参数

修改

在最后一个构造函数调用之后调用实例初始值设定项。 - Sotirios Delimanolis 6月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

2 个答案:

答案 0 :(得分:1)

(因为早先的答案不对,所以改了)

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

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

关注JLS第12.5节:

  

如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用this),则使用这五个相同的步骤计算参数并以递归方式处理该构造函数调用。

在JLS 8.8.7中:

  

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

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

答案 1 :(得分:0)

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

现在method()是一个实例方法,意味着需要在ClassForTest类型的Object上调用它。上面的代码基本上意味着

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

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

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