package zhiyinyong;
public class StaticTest {
public static int k=0;
public static StaticTest s1=new StaticTest("s1");
public static StaticTest s2=new StaticTest("s2");
public static int i=print("i");
public static int n=99;
public int j=print("j");
{
print("构造块");
}
static
{
print("静态块");
}
public static int print(String s)
{ System.out.println("nihao");
System.out.println(++k+":"+s+"\ti="+i+"\tn="+n);
++n;
System.out.println("hahn="+n);
return ++i;
}
public StaticTest(String s)
{ System.out.println("haohao");
System.out.println(++k+":"+s+"\ti="+i+"\tn="+n);
++i;
System.out.println("nimei="+i);
++n;
System.out.println("gunsn="+n);
}
public static void main(String[] args) {
new StaticTest("init");
}
}
运行结果:
nihao
1:j i=0 n=0
hahn=1
nihao
2:构造块 i=1 n=1
hahn=2
haohao
3:s1 i=2 n=2
nimei=3
gunsn=3
nihao
4:j i=3 n=3
hahn=4
nihao
5:构造块 i=4 n=4
hahn=5
haohao
6:s2 i=5 n=5
nimei=6
gunsn=6
nihao
7:i i=6 n=6
hahn=7
nihao
8:静态块 i=7 n=99
hahn=100
nihao
9:j i=8 n=100
hahn=101
nihao
10:构造块 i=9 n=101
hahn=102
haohao
11:init i=10 n=102
nimei=11
gunsn=103
解析:
1 2 3 4 |
|
先加载静态成员变量,初始化为默认值,K为0,s1=null,s2=null,其他类似。
然后准备给静态变量赋值,赋值到s1,这出现个对象,然后就转向来创建这个对象来。
因为静态成员只初始化一次,所以静态成员不用初始化了。直接初始化实例变量和实例代码块。
因而输出
1 2 |
|
然后,最后构造函数初始化,所以
Java code?
1 |
|
输出6:之前类似。然后创建两个对象后又回来了,接着初始化赋值。
赋值执行
1 2 |
|
此时已经初始化静态变量完毕。
下面应该初始化静态块
static
{
print("静态块");
}
然后所有静态都已经初始化完毕,然后初始化成员变量。最后调用构造方法。静态方法在第一次调用的时候就初始化。
在main方法中语句:(1)new StaticTest("init");和类的字段赋值语句(2)new StaticTest("s1");二者都是要创建类的对象。
main方法中的语句(1)执行的很晚很晚,因为main方法想要运行,系统发现类竟然还没载入,于是载入类并进行系统默认的初始化行为;但是这个系统初始化行为中间发生了递归初始化。
系统载入类,接着系统自动完成类的默认初始化,此时的值就是0值和null值两类;
既然是初始化,我们要注意两大类:静态的和非静态的;在载入、初始化的过程中,如果没有使用new 的方式创建对象,那么系统是不会对类的非静态变量进行 默认初始化的,即使是0值和null值,也没有,JVM根本就不会理会非静态变量。现在使用了new,那么初始化就会涉及到对非静态变量的初始化。
运行开始
main方法激发类的加载,紧接着系统对静态变量完成了默认初始化,静态对象类型是null值,普通类型是0值;非静态变量,还没有进行任何处理,连默认值也没有;此时JVM还没对非静态变量做任何处理;
首先对k进行初始化,k的系统默认初始化值是0,此时进行赋值,再次被赋值为0,
到了(2)系统此时发现s1是一个对象,值为null(这个null是系统默认初始化得到的),要对s1进行赋值;这个地方就发生了“在未完成初始化的类上调用new” 系统如何处理的呢?我的看法是:系统按照正常流程走,跟在其他地方使用new创建对象完全一样。
这里就是嵌套初始化或者叫做递归初始化:在初始化自己的过程中,初始化自己。
系统会进行类的加载,并进行静态变量的初始化,但是系统发现类的静态变量已经完成了初始化,此时是使用了new 创建对象会涉及到非静态变量的初始化,那么直接到 public int j=print("j"); ,执行非静态变量的初始化。