java 循环 跳转代码块_Java中静态初始代码块循环的问题

在啃《The Java Programming Language 4th Edition》时看到的一个小知识点。先描述一下问题。

一个类中,静态初始代码块中的代码会在类加载时自动运行。考虑下面这种情况:

ClassA定义了静态初始代码块,其中调用了ClassB的一个方法m(静态非静态均可)。而在ClassB的m方法中,又使用了ClassA类的信息。则,当虚拟机在没有ClassB类的情况下,加载ClassA类时,会遇到这样一条线索:

加载ClassA --> 调用ClassA的静态初始化代码块 --> 调用ClassB的m方法 --> 加载ClassB --> 使用ClassA的信息

注意这条线索的一头一尾,我们要在对ClassA还没完成加载时,使用ClassA的信息!

示例代码:

1

1fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifpublicclassTestStaticInit9b8a8a44dd1c74ae49c20a7cd451974e.png{297e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidmain(String args[])9b8a8a44dd1c74ae49c20a7cd451974e.png{3d18c02628675d0a2c816449d98bda930.png  ClassA a=newClassA();4ecedf933ec37d714bd4c2545da43add2.png }58f1ba5b45633e9678d1db480c16cae3f.png}64f1150b881333f12a311ae9ef34da474.png71fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifclassClassA9b8a8a44dd1c74ae49c20a7cd451974e.png{8d18c02628675d0a2c816449d98bda930.pngstaticinta1;9d18c02628675d0a2c816449d98bda930.pngstaticinta2;1097e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifstatic9b8a8a44dd1c74ae49c20a7cd451974e.png{11d18c02628675d0a2c816449d98bda930.png  a1=10;12d18c02628675d0a2c816449d98bda930.png  ClassB.print();13d18c02628675d0a2c816449d98bda930.png  a2=30;14ecedf933ec37d714bd4c2545da43add2.png }158f1ba5b45633e9678d1db480c16cae3f.png}164f1150b881333f12a311ae9ef34da474.png171fa987a29c6482f53d401256f96355eb.png

ca75c07623e1b494fee67e8f316fc310.gifclassClassB9b8a8a44dd1c74ae49c20a7cd451974e.png{1897e794c86028c5f5b5461ae5ef440a4c.png

3c6cafce68eb941a00f1998f1d3d3aa6.gifpublicstaticvoidprint()9b8a8a44dd1c74ae49c20a7cd451974e.png{19d18c02628675d0a2c816449d98bda930.png  System.out.println(ClassA.a1);20d18c02628675d0a2c816449d98bda930.png  System.out.println(ClassA.a2);21ecedf933ec37d714bd4c2545da43add2.png }228f1ba5b45633e9678d1db480c16cae3f.png}234f1150b881333f12a311ae9ef34da474.png244f1150b881333f12a311ae9ef34da474.png

首先,编译器无法解决这个问题,因为在编译ClassA类时,无法找到ClassB的代码,也就无法检查是否存在静态初始化代码块循环问题。事实上,上述程序在java中是能够编译通过的。

其次,运行时的结果。当程序运行到第3行时,JVM加载ClassA类,此时,会执行ClassA类中的静态初始化代码块。当程序执行到第12行时,调用ClassB的print方法,此时,程序跳转到18行。

关键在这儿:此时的print方法需要调用ClassA的信息,并打印其静态属性。而ClassA的信息正在加载过程中。此时,JVM采用的策略是:在print方法中使用ClassA不完整的信息。在print方法中ClassA的信息,是在第12行对ClassB.print方法之前的信息。此时ClassA.a1已经被赋值为10,而ClassA.a2还未被赋值,它的值为默认值。因此,最后打印出的是10、0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值