在上一篇文章中, 探索了在一条继承链中静态初始化块和静态变量初始化、初始化块和实例域初始化、构造函数的执行顺序(见
http://blog.youkuaiyun.com/maple1997/article/details/79508981),现在继续探索一下如果new一个自身类的对象赋值给静态变量来初始化的执行顺序会是怎么样。
以下是代码:
1.main()所在的类最先加载, 再执行main方法
2.在main方法中, 一边运行一边加载所需要的类
3.new自身类对象来初始化静态变量的顺序:
之前的static{}和静态变量的初始化,
{}和实例域的初始化,
构造函数,
之后的static{}和之后的静态变量的初始化
发现{}和实例域的初始化还有构造函数的执行的次序被提前了!(按照正常的顺序应该是:静态初始化块和静态变量初始化>初始化块和实例域初始化>构造函数),那么如果在实例域中使用还没有被初始化的静态变量的值会发生什么呢?
以下是代码:
package initialization;
//new自身类对象来初始化静态变量, 观察构造顺序
public class StaticVarNewItselfTest {
static
{
System.out.println("main方法所在的类被加载\n");
}
public static void main(String[] args) {
System.out.println("main开始");
AnotherClass c = new AnotherClass();
System.out.println("开始构造一个对象");
StaticVarNewItself t2 = new StaticVarNewItself();
System.out.println("main结束");
}
}
class StaticVarNewItself{
public StaticVarNewItself(){
System.out.println("new ()");
}
// new自身类对象来初始化静态变量
static
{
System.out.println("static blockB1");
}
public static StaticVarNewItself t1 = new StaticVarNewItself();
{
System.out.println("blockA");
}
static {
System.out.println("static blockB2");
}
}
class AnotherClass{
static {
System.out.println("AnotherClass加载");
}
}
运行结果:
main方法所在的类被加载
main开始
AnotherClass加载
开始构造一个对象
static blockB1
blockA
new ()
static blockB2
blockA
new ()
main结束
结果分析:
1.main()所在的类最先加载, 再执行main方法
2.在main方法中, 一边运行一边加载所需要的类
3.new自身类对象来初始化静态变量的顺序:
之前的static{}和静态变量的初始化,
{}和实例域的初始化,
构造函数,
之后的static{}和之后的静态变量的初始化
发现{}和实例域的初始化还有构造函数的执行的次序被提前了!(按照正常的顺序应该是:静态初始化块和静态变量初始化>初始化块和实例域初始化>构造函数),那么如果在实例域中使用还没有被初始化的静态变量的值会发生什么呢?
package initialization;
//new自身类对象来初始化静态变量, 观察构造顺序
public class StaticVarNewItselfTest {
static
{
System.out.println("main方法所在的类被加载\n");
}
public static void main(String[] args) {
System.out.println("main开始");
AnotherClass c = new AnotherClass();
System.out.println("开始构造一个对象");
StaticVarNewItself t2 = new StaticVarNewItself();
System.out.println("StaticVarNewItself.staticValue = " + StaticVarNewItself.staticValue);
System.out.println("StaticVarNewItself.t1.value = " + StaticVarNewItself.t1.value);
System.out.println("StaticVarNewItself.t2.value = " + t2.value);
System.out.println("main结束");
}
}
class StaticVarNewItself{
public StaticVarNewItself(){
System.out.println("new ()");
value = staticValue;
System.out.println("使用了静态变量staticValue的值");
}
// new自身类对象来初始化静态变量
static
{
System.out.println("static blockB1");
}
public static StaticVarNewItself t1 = new StaticVarNewItself();
{
System.out.println("blockA");
}
static {
System.out.println("static blockB2");
}
public static int staticValue;
static {
//经过一些复杂的计算
staticValue = 250;
System.out.println("静态变量staticValue初始化完成");
}
int value;
}
class AnotherClass{
static {
System.out.println("AnotherClass加载");
}
}
运行结果:
main方法所在的类被加载
main开始
AnotherClass加载
开始构造一个对象
static blockB1
blockA
new ()
使用了静态变量staticValue的值
static blockB2
静态变量staticValue初始化完成
blockA
new ()
使用了静态变量staticValue的值
StaticVarNewItself.staticValue = 250
StaticVarNewItself.t1.value = 0
StaticVarNewItself.t2.value = 250
main结束
所有的一切都安安静静地发生,MyEclipse编译器不会警告,运行时也没有抛异常,只是并没有像预期那样取得静态变量staticValue的值,而是取到了默认值0。这说明了如果一个类的静态变量的初始化需要new一个自身类的对象, 则一定要注意其他静态变量的初始化和获取该静态变量的值的先后次序。