超types构造函数被调用之前不能引用“X”,其中x是最后一个variables

考虑下面的Java类声明:

public class Test { private final int defaultValue = 10; private int var; public Test() { this(defaultValue); // <-- Compiler error: cannot reference defaultValue before supertype constructor has been called. } public Test(int i) { var = i; } } 

编译器不会编译,抱怨上面突出显示的那一行。 为什么这个错误发生,什么是最好的解决方法?

代码最初不能编译的原因是因为defaultValue是类Test一个实例variables ,这意味着当一个Testtypes的对象被创build时,一个唯一的defaultValue实例也被创build并被附加到该特定对象上。 因此,在构造函数中引用defaultValue是不可能的,因为它既没有创build对象,也没有创build对象。

解决的办法是让最后一个variablesstatic

 public class Test { private static final int defaultValue = 10; private int var; public Test() { this(defaultValue); } public Test(int i) { var = i; } } 

通过将variables设置为staticvariables,variables与类本身相关联,而不是该类的实例,并在Test所有实例中共享。 静态variables在JVM首次加载类时创build。 由于类在您使用它创build实例时已经加载,因此可以使用静态variables,因此可以在类中使用,包括构造函数。

参考文献:

  • 论坛post问同样的问题
  • 了解实例和类成员
  • 类加载器如何加载静态variables的说明

这是因为defaultValue是正在构build的Test实例的成员(尚未创build)

如果你是static ,当你的类加载类加载器时,它会被加载

规则:每个构造函数在执行之前都必须执行超类的构造函数。

因此,每个构造函数的第一行是super()或者可能是this(),并且您将defaultValue发送给此类构造函数,该函数的defaultValue不存在,因此存在编译时错误。

您可以将defaultValue设置为static,并且由于将类加载到内存中时创build静态variables,所以defaultValue在this(defaultValue)行可用。

直到你的对象没有被构造,variables的默认值将不会被设置,因此如果你希望在构造时设置它们的默认值,使它们成为static或者明确地设置它们。

构造函数在对象创build时被调用,所以编译器不会识别可变参数,因为编译器没有关于实例variables的知识,因为对象还没有被创build。

其实这是不正确的答案,因为在创build对象期间,字段初始化指令在构造函数之前执行。 您可以debugging对象创build过程并自行查看。 我自己也对这个问题感到困惑。例如,如果你会改变一点,第一个构造函数将是:

 public Test(int i) { this(i, 0); } public Test (int a, int k) { } 

这将工作..所以,当第一个/空构造函数调用另一个,它不工作的一个奇怪的原因,即使我显式调用super(); 之前。

最相关的解释是,JVM在内存中加载声明,但是在它完全执行之前,没有任何构造者可以达到任何实例variables/字段

你正在引用一个不存在的variables,如果它是静态的,所以它甚至会在构造函数本身之前存在

但你会面临另一个问题,因为defaultValue变成静态的,所以其他的实例可能会共享相同的值,你可能不喜欢它,

 public class Test { private final int defaultValue = 10; //this will be exists only after calling the contractor private final static int vakue2= 10; //this is exists before the contractor has been called private int var; public Test() { // this(defaultValue); // this metod will not work as defaultValue doesn't exists yet this(value2); //this will work //this(10); will work } public Test(int i) { var = i; } } 

在这个话题下,我一直在关注这个问题。

 class Super{ int a=10; static int x=100; Super(){ System.out.println("Super()"); } Super(int i){ System.out.println("Super(int)"); } } class Sub extends Super{ int b=20; static int y=20; Sub(int i){ ***Super(b);*** System.out.println("Sub(int)"); } } 

super和sub类的实例variables,我们不能用于引用。 因为实例variables是在构造函数运行之后初始化的。 而variables不是最终的和静态的。 值可以改变。 以及这些只有实例variables,因此我们碰巧创build对象来初始化这个variables。所以这个variables不能用于引用。 但是如果这个variables是最终的和静态的,那么这些variables只保留模板。 以及这些variables具有特定的值,这些不变。 因此,我们可以调用超类构造函数使用这些静态最终variables。