posts - 13,  comments - 3,  trackbacks - 0

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

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

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

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

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

示例代码:

 1public class TestStaticInit{
 2 public static void main(String args[]){
 3  ClassA a= new ClassA();
 4 }

 5}

 6
 7class ClassA{
 8 static int a1;
 9 static int a2;
10 static{
11  a1 = 10;
12  ClassB.print();
13  a2 = 30;
14 }

15}

16
17class ClassB{
18 public static void print(){
19  System.out.println(ClassA.a1);
20  System.out.println(ClassA.a2);
21 }

22}

23
24

 

首先,编译器无法解决这个问题,因为在编译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。

posted on 2009-01-05 23:48 Antony Lee 阅读(418) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 

<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(1)

随笔分类

随笔档案

文章分类

搜索

  •  

最新评论

阅读排行榜

评论排行榜