直接上例子来说明比较直观.
准备工作:
Class A:
package com.ld.test;
/**
* Created by 123 on 2018/4/13.
*/
public class A {
private static String a_mark1 = initA_Mark1();
private String a_mark2;
static {
System.out.println("This is static code block of A.");
System.out.println(a_mark1);
}
{
System.out.println("This is code block of A.");
if(a_mark2 == null) {
System.out.println("a_mark2 is null");
} else {
System.out.println(a_mark2);
}
}
public A() {
System.out.println("This is default constructor of A.");
a_mark2 = "a_mark2";
System.out.println(a_mark2);
}
private static String initA_Mark1() {
System.out.println("This is static initialized method of A.");
return "a_mark1";
}
}
Class B:
package com.ld.test;
/**
* Created by 123 on 2018/4/13.
*/
public class B extends A {
private static String b_mark3 = initb_mark3();
private String b_mark4;
static {
System.out.println("This is static code block of B.");
System.out.println(b_mark3);
}
{
System.out.println("This is code block of B.");
if(b_mark4 == null) {
System.out.println("b_mark4 is null");
} else {
System.out.println(b_mark4);
}
}
public B() {
System.out.println("This is default constructor of B.");
}
public B(String b_mark4) {
this();
System.out.println("This is custom constructor of B.");
this.b_mark4 = b_mark4;
System.out.println(b_mark4);
}
private static String initb_mark3() {
System.out.println("This is static initialized method of B.");
return "b_mark3";
}
public static void main(String[] args) {
System.out.println("Execute main method.");
B b = new B("b_mark4");
System.out.println("Initialization end.");
}
}
*说明: A,B两类在同一包下(com.ld.test), B继承自A.
---------------------------------------------------------------------------------------------------
执行B类的main方法....
---------------------------------------------------------------------------------------------------
执行结果:
This is static initialized method of A.
This is static code block of A.
a_mark1
This is static initialized method of B.
This is static code block of B.
b_mark3
Execute main method.
This is code block of A.
a_mark2 is null
This is default constructor of A.
a_mark2
This is code block of B.
b_mark4 is null
This is default constructor of B.
This is custom constructor of B.
b_mark4
Initialization end.
稍微了解java的同学都知道, 类是在jvm启动后才会加载. 但有想过是在什么时候加载吗? 根据上面的例子不难看出, 一定是在使用这个类的静态资源或者创建这个类的对象的时候才会加载, 本例中属于在使用类的静态资源的时候加载. 别忘了,B类中的main方法也是静态的, 它也属于类的静态资源, 所以当执行main方法时类就被加载了.
1. 首先肯定要先加载静态资源, 而B又继承自A, 所以先加载A类中的静态成员和静态代码块, 所以先执行initA_Mark1()方法,输出"This is static initialized method of A.", 并将a_mark1的值初始化为"a_mark1".
2. A类中的静态成员初始化完成后, 紧接着就该执行A类的静态代码块, 所以输出"This is static code block of A.", 并打印a_mark1的值"a_mark1".
3. A类中的静态成员和静态代码块执行完后, 就轮到子类B了, 所以执行B类中的initB_mark3()方法, 输出"This is static initialized method of B.", 并将b_mark3的值初始化为b_mark3.
4. 接着是B类中的静态代码块, 输出"This is static code block of B.", 打印b_mark3值"b_mark3".
5. 现在A, B两个类的静态部分都加载完成, 所以执行main方法中的第一行代码, 输出"Execute main method."
6. 接着执行第二行代码"B b = new B("b_mark4");", 因为这里创建了一个B的对象, 而B又继承自A, 所以会先创建一个A的对象.
7. A类中非静态的代码块会首先执行, 非静态代码块的作用就是在构造方法之前做一些额外的初始化操作. 现在执行A类中的代码块,输出"This is code block of A.", 并判断成员变量a_mark2的值是否为空, 若为空则输出提示语:"a_mark2 is null", 不为空则输出a_mark2的值. 因为a_mark2还未被初始化, 所以jvm默认赋给它一个null, 所以会输出提示语:"
a_mark2 is null".
8
. 代码块执行完后, 为了确保A类对象创建成功(对象完成初始化), jvm会调用A类的默认构造方法, 所以输出"This is default constructor of A.", 并将成员a_mark2的值赋为"a_mark2", 随后打印a_mark2值, 输出"a_mark2". 至此, A类的对象完成创建.
9
. B类对象的创建与上述流程一样, 也是先执行代码块,输出"This is code block of B.", 对B类中成员变量b_mark4进行非空判断, 同上, 所以输出"b_mark4 is null".
10
. 因为在创建B对象的时候传入了参数, 所以会调用B类中的有参构造方法.
11. 在该构造方法中, 可以看到执行了"this();", 这句代码会调用B类的默认构造方法(这句代码必须写在第一句), 所以会先输出"This is default constructor of B.", 然后回到有参构造方法中,输出"This is custom constructor of B.", 将成员变量b_mark4的值初始化为创建B对象时传入的参数, 再输出b_mark4值"b_mark4", 至此,完成了B对象的创建.
12. 执行main方法中的最后一句代码, 输出"Initialization end.", 完成整个类的加载和对象的创建.
总结:
* 类中静态资源首次加载的时间是类中静态资源第一次被调用的时候或者该类的对象第一次被创建的时候
* 类按照 静态成员 --> 静态代码块 --> 普通成员 --> 代码块 --> 构造方法 的顺序来加载.
* 在创建一个类的对象时, 如果该类有父类, 则先执行父类对象的创建, 各部分加载的顺序也是按上述顺序加载
* 别忘了main方法也属于类的静态资源.