为什么这个代码在右侧使用显式静态字段表示法编译,但不是没有?
public class A
{
static int a = ++A.a; // compiles
//static int a = ++a; // error - cannot reference a field before it is defined
public static void main(String[] args) {
System.out.println(a);
}
}
答案 0 :(得分:4)
这就是语言规范的编写方式。具体来说,Sec 8.3.3说:
对字段的引用有时会受到限制,即使字段在范围内也是如此。以下规则约束对字段的前向引用(在文本上使用字段声明之前)以及自引用(字段在其自己的初始化程序中使用)。
对于对简单名称的引用,对类中声明的类变量f 或接口C,如果:
,则编译时错误
- ...
强调我的。
A.a
不是一个简单的名称,因此它不是编译时错误。
答案 1 :(得分:1)
除了@Andy的回答,我想展示一些从这个JLS chapter中获取的例子。他们解释了使用前宣言规则,展示了有效的&无效案件:
class UseBeforeDeclaration {
static {
int a = UseBeforeDeclaration.b + 2; // ok - 'b' is not accessed via simple name
}
{
c = 1000000; // ok - assignment
c = c + 100; // error - right hand side reads before declaration
int d = c++; // error - read before declaration
int e = this.c * 2; // ok - 'c' is not accessed via simple name
}
static int b;
int c;
}
此外,在对有效static int a = ++A.a
行进行字节码调查之后,我们可以看到它被编译成:
static <clinit>()V
L0
LINENUMBER 4 L0
GETSTATIC src/java/A.a : I
ICONST_1
IADD
DUP
PUTSTATIC src/java/A.a : I
PUTSTATIC src/java/A.a : I
RETURN
相当于:
public class A {
static int a;
static {
++a;
}
public static void main(String[] args) {
// ...
}
}