【问题标题】:Why cannot I invoke nonstatic methods as this argument in constructor? [duplicate]为什么我不能在构造函数中调用非静态方法作为这个参数? [复制]
【发布时间】:2014-07-21 19:55:16
【问题描述】:

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

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

你能解释一下吗?

更新

据我了解,编译器会合并以下初始化块:

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

我不明白为什么我不能将此调用用作构造函数的参数

编辑

在最后一次构造函数调用之后调用实例初始化器。 – 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

【问题讨论】:

  • in重复的问题没有解释有效代码3
  • 实例初始化器在最后一次构造函数调用之后被调用。
  • public class Order { {public class Order { { System.out.println("initializer!"); } Order(){ System.out.println("constructor"); } public static void main(String [] args){ new Order(); } } System.out.println("初始化器!"); } Order(){ System.out.println("constructor"); } public static void main(String [] args){ new Order(); } }
  • @Sotirios Delimanolis 你错了
  • 我可以在初始化块中引用这个指针。此块在构造函数之前执行,因此未设计对象但我可以调用它。

标签: java methods constructor instance


【解决方案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() 的主体之前进行评估。但是,规范禁止这样做,因为对象的状态可能尚未完全初始化,例如对于一个类型的子类,其构造函数设置子类型继承的某些状态。

【讨论】:

  • 有效代码3呢?
  • @gstackoverflow 初始化块运行之后 this() 和/或super() 被调用,所以块是好的
  • 嗯,有趣的顺序!
  • @gstackoverflow 如果您想了解更多信息,请查看 JLS 的第 12.4 和 12.5 节,其中指定了初始化类、接口和对象的确切步骤。
  • 我知道这个顺序是对的,但是已经够乱了。
【解决方案2】:
class ClassForTest{
    ClassForTest(int k){
    };
    ClassForTest(){
         this(method());
    };
    int method(){return 1;}
}

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

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

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

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

【讨论】:

  • 有效代码 3 怎么样?方法调用发生在构造函数调用之前!!!
猜你喜欢
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 2011-11-16
  • 1970-01-01
  • 2013-10-01
  • 2022-01-04
相关资源
最近更新 更多