我有以下代码:
public class Main {
private int i = j; //1
private int j = 10;
public static void main(String[] args) {
System.out.println((new Main()).i);
}
}
并且第1行中存在编译器错误,因为它是非法的 前瞻性参考 但是当我尝试以下代码时:
public class Main {
int i = getJ(); //1
int getJ(){
return j;
}
int j=10;
public static void main(String[] args) {
System.out.println(new Main().i);
}
}
它工作正常,结果为0.
为什么没有非法
这里第1行的前向参考?这两个代码与我类似。
答案 0 :(得分:6)
可以在声明方法之前使用方法。
private int j = 10;
是一个必须在某个时间点执行的可执行语句。因此,字段声明的顺序是有意义的。
方法声明本身不可执行 因此,方法的排序完全没有意义。
答案 1 :(得分:4)
该规则仅适用于字段。具体来说(JLS 8.3.2.3):
成员的声明需要 在使用之前以文本方式显示 仅当成员是实例时 一个类的(分别是静态的)字段 或接口C和所有的 以下条件成立:
- 用法发生在实例(分别是静态)变量中 C的初始化程序或实例 (分别是静态的)初始化器 下进行。
- 用法不在作业的左侧。
- 使用方法是一个简单的名称。
- C是封闭用法的最里面的类或接口。
第一个例子的所有条件都适用。
至少有一个(“通过简单名称使用”)不适用于第二个示例。基本上,编译器尝试捕获循环错误,如:
int i = j + 1;
int j = i + 1;
这有点过于谨慎,但它大部分都有效。在执行j = 10之前,j仍为0,因此i的值被设置为。没有办法扩展你的getJ示例来创建一个循环(当然,还有其他方法可以在运行时创建无限递归)。
答案 2 :(得分:2)
因为您在实例初始化完成之前显式调用方法并访问成员变量。编译器可以阻止你做多么愚蠢的事情是有限的! : - )
答案 3 :(得分:2)
Java运行时有一个信息,你有一个实例变量,它是int,称为“j” 但是,在字节码解释器到达初始化之前,该值不会设置为10。
这就是您将默认int值视为返回值的原因。
答案 4 :(得分:0)
J在被引用以进行赋值之前未被声明