java中的类和接口初始化
下面是代码java中的类和接口初始化,java,Java,下面是代码 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 ClassAndInterfac
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
加载并链接类Z
后,在初始化阶段,变量j
作为final
首先用1
初始化。变量k
也用1
初始化
但是对于变量k
,输出给出0
我如何理解这一点
注意:编译器实际上会替换变量
j
的值,只要它是按照正向引用规则引用的,这与k
不同,您试图在初始化变量k
之前访问它,这就是为什么它是0。(h
在定义k
之前被初始化为peekk()
,因此peekk()
返回0,因为字段是从上到下初始化的。)j
是最终的,所以首先执行;在声明i
之前,因此i
获取j
或1的值
适当的Oracle文档:
接下来,按照文本顺序执行类的类变量初始值设定项和静态初始值设定项,或者执行接口的字段初始值设定项,就像它们是单个块一样
static final int
将使j
成为编译时常量。因此,它的值将作为字节码本身的一部分呈现和传递。因此,初始化类时,j
将为1。但是k
只是static int
,因此它的默认值将被打印出来,因为静态初始值设定项在k
值初始化之前运行。在编译代码时,“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;
同样的情况也发生在
j
上。但由于编译时替换(如LostMind的回答中所述),它给出了正确的结果。@TimBiegeleisen我做到了。还有一个问题:System.out.println(Z.peek())代码>输出1,其中asSystem.out.println(Z.h)代码>输出0。怎么做?当你说“在初始化之前尝试访问k,这就是为什么它是0”时,你是说,在初始化阶段之前有一个单独的阶段,k
被设置为0?是的,那个阶段是什么?基本上。Java将在所有其他代码运行之前(在编译时,IIRC)为所有代码提供默认值代码>输出1,其中asSystem.out.println(Z.h)代码>输出0。如何?@overexchange Yes所有出现的“J”都被实际数字1替换。请看下面我的答案。还有一个问题:System.out.println(Z.peek())代码>输出1,其中asSystem.out.println(Z.h)代码>输出0。如何?一旦调用了System.out.println(Z.peek())
,所有变量都被正确初始化(为1)。在main方法中:System.out.println(Z.i);System.out.println(Z.peek());系统输出打印ln(Z.h)代码>。输出:主方法中的1 1 0:System.out.println(Z.peek());系统输出打印ln(Z.h)代码>。产出:10。产量没有变化。注意:即使我更改了SOP的顺序,行为也一样。@NamanGala-这是因为当h
被初始化时,k是0
。但是peek()
在调用方法时返回k
的当前值。您正在初始化类后调用方法。所以,值是1。明白了吗?一个补充,不同原始数据类型的默认值是什么?@overexchange单击此处并向下滚动查看表格