public class A{
static String a = "aaa";
static String b = new B().sayHi_B();
static{
System.out.println("A.static:A's vars are:{" + A.a + ',' + A.b+ "}");//2
}
void sayHi_A(){
System.out.println("A.sayHi():A's vars are:{" + A.a + ',' + A.b+ "}");//3
}
public static void main(String[] args){
}
}class B{
static{
System.out.println("B.static #1:A's vars are:{" + A.a + ',' + A.b+ "}");//1
new A().sayHi_A();
System.out.println("B.static #2:A's vars are:{" + A.a + ',' + A.b+ "}");//4
}
String sayHi_B(){
return "HI";
}
}
//我的答案
//B.static #1:A's vars are:{aaa,null}
//A.static:A's vars are:{aaa,null}
//A.sayHi():A's vars are:{aaa,null}
//B.static #2:A's vars are:{aaa,HI}//实际答案
//B.static #1:A's vars are:{aaa,null}
//A.sayHi():A's vars are:{aaa,null}
//B.static #2:A's vars are:{aaa,null}
//A.static:A's vars are:{aaa,HI}
基本信息的加载指声明类变量及方法、实例属性及方法等基本信息,并将类变量置默认值。初始化指类变量的初始化及静态块的运行,它们按从上到下的顺序执行。本例中,先加载主类A:
1.声明类变量a、b,实例方法sayHi_A,并将a、b置默认值null。
2.初始化类变量a="aaa"。
3.由于类变量b的初始化用到了类B,所以这里暂停A的加载,转入B的加载。
4.声明实例方法sayHi_B。
5.执行静态块,由于A.a已初始化为aaa,而A.b由于类B的加载而未初始化,仍然为null。输出B.static #1:A's vars are:{aaa,null}。
6.由于类A的基本信息已加载完成,所以可以调用其实例方法sayHi_A(注:类能够实例化的前提是基本信息加载完成而不是初始化完成,否则像本例的情况会因为A与B争先初始化而发生死锁),输出A.sayHi():A's vars are:{aaa,null}。
7.静态块的第三行,输出B.static #2:A's vars are:{aaa,null}。
8.完成类B的初始化,继续A的初始化。调用B的实例方法初始化A.b="HI"。
9.运行静态块,输出A.static:A's vars are:{aaa,HI}。
10.类A初始化完成。说实说,这个题目真的很奇葩(虽然利用非静态块和构造函数同样可以设计出很奇葩的题目……)。