从一个小Demo入手
public class Demo1 {
static Demo1 demo1 = new Demo1();
String name1 = "wkw";
Demo1() {
System.out.println("我是构造函数");
}
{
System.out.println("我是非静态块" + name1 + name2);
}
static String name2 = "yhr";
static {
System.out.println("我是静态块" + name2);
}
public static void main(String[] args) {
new Demo1();
}
}
以下是输出内容
我是非静态块wkwnull
我是构造函数
我是静态块yhr
我是非静态块wkwyhr
我是构造函数
从输出可以看出来,类初始化的时候是先加载静态资源,没有先后顺序,从上到下依次加载,
1.首先加载static Demo1 demo1 = new Demo1();
,执行到这一句的时候会去加载非静态块的内容,然后再执行构造函数。这里其实在编译成class文件的时候非静态的内容是在构造函数上面的,两个结合了。
Demo1() { System.out.println("我是非静态块" + this.name1 + name2); System.out.println("我是构造函数"); }
2这里还有个需要注意点的是静态变量name2的声明放在了非静态块的下面,非静态块引用了name2,然后执行上面的第一个静态变量的时候我当时认为name2还没有声明,是怎么取到值的,后来在class文件里面看到name2定义提升到了方法的前面
static Demo1 demo1 = new Demo1();
String name1 = "wkw";
static String name2 = "yhr";
而且是先声明后赋值,所以才有了第一个输出name2是null的情况,此时name2还没有赋值。
为此我专门做了个实验
public class Demo2 {
String a = "a";
String b = b();
String c = "c";
public String b() {
System.out.println(b);
return a + c;
}
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
demo2.b();
System.out.println(demo2.b);
System.out.println(demo2.c);
}
}
结果:
null
anull
anull
c
由于按顺序执行变量的初始化,所以变量b初始化的时候调用了b()方法,此时a初始化完成,c没初始化完成,所以b的值是anull,此时执行到b能调用c变量说明类初始化的时候是先定义变量,再对变量进行赋值的。
相当于:
String a;
String b;
String c;
{
a = "a";
b = b();
c = "c";
}
3.接下来再执行静态块的内容,执行完以后就开始执行非静态块,再执行构造函数。
到这里大家应该清楚他们的执行顺序了吧,静态块先执行只执行一次,非静态块后执行,编译的时候把非静态块的内容放到了构造函数的上面,最后再执行构造函数。