Java 向超级构造函数传递值时无法从静态上下文访问字段
我遇到了一个非常奇怪的编译时错误:Java 向超级构造函数传递值时无法从静态上下文访问字段,java,inheritance,static,Java,Inheritance,Static,我遇到了一个非常奇怪的编译时错误: class Super { Super(int[] array) { } } class Sub extends Super { private final int number = 1; Sub() { super(new int[] { number }); //error } } 我得到的错误是 无法从静态上下文访问字段 我的问题 静态上下文在哪里?在这里,静态似乎都不起作用 我在试图回答别
class Super {
Super(int[] array) {
}
}
class Sub extends Super {
private final int number = 1;
Sub() {
super(new int[] { number }); //error
}
}
我得到的错误是
无法从静态上下文访问字段
我的问题
静态上下文在哪里?在这里,静态似乎都不起作用
我在试图回答别人的问题时偶然发现了这一点;我发现了让我困惑的错误。有人能解释一下静态上下文在哪里吗?您的字段<代码>编号应该是静态的,这样您就可以在构造函数调用中使用它了。否则,在调用超类型构造函数之前,您将获得
无法引用编号,因为在调用父类的构造函数之前,该字段不可访问
因此,您的代码应该如下所示:
class Super {
Super(int[] array) {
}
}
class Sub extends Super {
private static final int number = 1;
Sub() {
super(new int[] { number }); //error
}
}
问题是,super
必须在子类中执行任何其他操作之前被调用。这意味着,number
在调用时未初始化,因此无法将其传递给super。
至于它与“静态上下文”有什么关系,我不确定
构造函数体中的显式构造函数调用语句不能引用该类或任何超类中声明的任何实例变量或实例方法或内部类,也不能在任何表达式中使用this
或super
;否则,将发生编译时错误
在super
调用时,Sub
的实例将不存在请尝试运行以下程序
public class Main {
public static class Super
{
Super(int number) {
System.out.println("A");
}
}
public static class Sub extends Super {
private final Thing thing = new Thing();
Sub() {
super(3);
System.out.println("B");
}
}
public static final class Thing {
Thing() {
System.out.println("C");
}
}
public static void main(String[] args) {
new Sub();
}
}
输出是A、C、B。首先运行Super
的构造函数,然后初始化Sub
的实例字段thing
。最后执行super
之后的Sub
构造函数的行
当您尝试引用编号
时,字段编号
尚未初始化,并且没有子
实例。错误消息可能更有帮助。在IntelliJ上,我得到“在调用超类型构造函数之前无法引用Sub.number” 类的加载是从子类(如果它有main方法或由其他类引起加载)到基类的,但是初始化是以相反的顺序进行的(基类将首先初始化)。基类初始化之前已完成,此时数字字段将不存在,因为它是实例变量
您可以使其静态(类变量)更早加载,如果其最终,则编译器将仅在编译时在常量池中创建一个条目。以便JVM能够获取其值。您使用的是哪种编译器?在调用超类型构造函数之前,我无法引用编号。另请参见JLS 8.8.7.1。显式构造函数调用,声明:“构造函数体中的显式构造函数调用语句不能引用该类或任何超类中声明的任何实例变量、实例方法或内部类,也不能在任何表达式中使用this或super;否则,会发生编译时错误。”@ZouZou我第一次在手机的ide助手上遇到它,我很确定它使用的是Dalvik编译器。然后我跳到我的计算机上,在EclipseLuna上使用他们的JDK8U25编译器进行了尝试,得到了相同的错误消息。我不确定为什么会出现静态上下文错误,所以我认为应该重新安装Eclipse。至于助手,我并不太惊讶它给了我一个可怕的错误+1。我认为你的最后一句话是关键。由于那里没有可用的实例,编译器实际上认为这是一个“静态上下文”,就像静态方法或静态初始化块或静态字段的初始化表达式一样。(就我个人而言,我认为编译器最好对此上下文使用单独的错误消息,这只是为了清晰和避免混淆。但约束条件与正常静态上下文中的约束条件相同,因此编译器编写人员可能太过倾向于不重复自己。)这不是我收到的错误,但是,应该显示的是正确的错误。这就是问题所在。那是几年前的事了,但回顾过去,这似乎是最好的答案。感谢您的贡献,很抱歉花了这么长时间才接受。尽管其他答案提到了JLS查询,但它并没有提示通知错误,也没有指定正确的通知是什么。