请看下面的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
,这意味着类型的对象,当Test
被创建,唯一的实例defaultValue
也被创建并连接到特定的对象。 正因为如此,它是不可能引用defaultValue
在构造函数中,既不的,也不对象已经被创建。
解决的办法是做最后的可变static
:
public class Test {
private static final int defaultValue = 10;
private int var;
public Test() {
this(defaultValue);
}
public Test(int i) {
var = i;
}
}
通过使该变量static
,它变得与类本身相关联,而不是类的实例,并且所有实例之间共享Test
。 当JVM首先加载类中创建静态变量。 因为当你使用它来创建一个实例的类已经被加载,静态变量就可以使用,因此可以在课堂上使用,包括构造。
参考文献:
- 论坛发帖问同样的问题
- 理解实例和类成员
- 类加载器加载如何静态变量的说明
这是因为, defaultValue
是的成员Test
的实例,它正在建设中(尚未创建)
如果你有它static
它被装在你的类加载由类加载器
规则:每一个构造函数必须执行自己之前执行的超类的构造函数。
所以,每一个构造函数的第一行是超(),或者可能是这样的()和你发送默认值到(默认值)尚未存在的这一类的构造函数,因此有编译时错误。
您可以制作默认值静态和自创建为类的静态变量被加载到内存中,因此默认值可在此(默认值)就行了。
您正在引用到一个变量这么想的还不存在 ,如果它是静态的 ,所以它会更加的构造本身存在之前
但你会面临另一个问题,因为默认值成为静态的,因此所有其他实例可以共享whitch你可能不喜欢它是相同的值,
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;
}
}
直到你的对象没有被构造默认值,如果你希望自己的默认值,在施工时设置不会因此设定的变量,使它们static
或之前明确设置它们。
构造函数在对象创建的这么varable没有提及是由编译器编译为认可的时候已经没有关于实例变量尚未创建的对象的知识。
其实这是不正确的答案,作为创建对象的过程中,字段初始化指令的构造函数之前执行。 您可以调试对象的创建过程,并看到你自己的。 我自己很困惑这个问题以及..例如,如果你改变了一下,第一个构造将是:
public Test(int i) {
this(i, 0);
}
public Test (int a, int k) {
}
这将工作..所以,当第一/ null的构造函数调用另一个,它不工作了奇怪的原因,即使我显式调用超(); 之前。
最相关的解释是,在内存中运行的JVM负载的声明,但没有构造能够以前被完全执行达成任何实例变量/场 。
文章来源: Cannot reference “X” before supertype constructor has been called, where x is a final variable