在下面的代码中,当使用类名访问静态变量时,它不会引发前向引用错误,但在没有类名的情况下访问它会引发前向引用错误。
为什么使用类名访问时不会发生这种情况?
class Test{
static {
System.out.println(a); // shows error
a = 99; // and this line too doesn't give error
System.out.println(Test.a); // this line doesn't
}
static int a = 10;
static{
System.out.println(a);
}
}
前向引用的规则定义在JLS §8.3.3 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.3.3:
使用其声明文本出现在
即使这些类变量位于
范围(第 6.3 条)。具体来说,如果所有的
以下是正确的:
所以,基本上你的第一个Sysout()
,满足上述所有 4 个条件,因此这是一个编译时错误。
在第2次Sysout()
,您正在访问a
使用它的限定名称,而不是简单名称,根据上述规则,这是允许的。
现在,原因是,当您访问Test.a
,编译器确定Test
类已加载并且所有static
字段已经初始化,因此可以访问该字段a
。但在访问时a
对于简单名称,编译器不确定初始化程序a
是否已经运行,因为它可能仍在加载类的过程中。
考虑以下类加载过程:
- 当一个类被加载时,内存被分配给所有的类
static
其中声明的变量。此时,变量a
已分配内存(声明完成)
- Then all the
static
initializers run in the order of occurrence.
- 第一个声明是
Sysout(a);
. a
尚未初始化,因此您无法访问它。 (错误)
- 第二个声明是
a = 99
。这里实际上是在初始化变量a
。完全没问题。
- 第三个是
Sysout(Test.a)
- 原因已在上面发布。编译器知道Test
已经加载。
- Then
static int a = 10
被执行。它重新初始化a
to 10
。请记住,声明部分已在第一步中处理完毕。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)