以下是代码,
class Z{
static int peekj(){
return j;
}
static int peekk(){
return k;
}
static int i = peekj();
static int h = peekk();
static final int j = 1;
static int k = 1;
}
public class ClassAndInterfaceInitialization {
public static void main(String[] args) {
System.out.println(Z.i);
System.out.println(Z.h);
}
}
遵循静态初始化的前向引用规则后,我将输出视为:
1
0
加载class Z
之后&链接,在初始化阶段,变量j
为final
首先使用1
进行初始化。变量k
也使用1
初始化。
但输出为变量0
提供了k
。
我如何理解这一点?
注意:编译器实际上会替换前向引用规则引用的变量j
的值,而不像k
答案 0 :(得分:6)
static final int
会使j
成为编译时常量。因此,它的值将作为字节代码本身的一部分出现并传递。因此,当您的类被初始化时,j
将为1 。但是k
只是static int
,因此自静态初始化程序以来将打印其默认值在初始化k
的值之前运行。
答案 1 :(得分:5)
您在初始化之前尝试访问k
,这就是为什么它是0.(h
在定义peekk()
之前初始化为k
,因此{ {1}}返回0,因为字段是从上到下初始化的。)peekk()
是最终的,所以它先执行;在声明j
之前,i
获得i
或1的值。
Here's相应的Oracle文档:
接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就像它们是单个块一样。
答案 2 :(得分:3)
" J"是一个常量,因此在编译代码时,j将被整个程序中的数字1替换。所以,如果你是一个外星人,你可以读取字节代码,代码看起来像这样
static int peekj(){
return 1;// j is replaced by the Actual Number 1
}
"静态变量在加载类时被初始化" 因此当类加载时,以顺序方式执行以下语句
static int i = peekj(); // Executed First, as peekJ() directly returns 1 so i is equal to 1
static int h = peekk(); // Executed Second, Now peekk() returns "THE VALUE OF k" which is not set yet i.e default value of int is given 0(zero)
//So h is equal to 0
static final int j = 1; // This statement doesn't exist as all j's are replaced with actual Number 1 when we compiled java to .class
static int k = 1; // Executed last, So now the value of 'k' is being set, after the value of 'h' has already been set to zero
注意:强> 这样做得到输出1和1,即i = 1和h = 1; 因为k的值首先被设置为1。
static int k = 1;
static int i = peekj();
static int h = peekk();
static final int j = 1;