先用文字描述:
类加载的过程 我自己抽象了下,可以分为
1、装载:查找和导入Class文件 2、3、初始化:对静态变量,静态代码块执行初始化工作
step1. 查找和导入Class文件(包括:二进制代码,class自描述信息)
step2. 链接:其中解析步骤是可以选择的 (a)检查:检查载入的class文件数据的正确性 (b)准备:给类的静态变量分配存储空间 (c)解析:将符号引用转成直接引用
step3. 对静态变量,静态代码块执行初始化工作(注意这里叫初始化--准备静态变量)
(step4: init 调用构造方法,一般需要被显示调用 如new ,子类new,反射类方法名等 这叫做实例化)
何时类加载被 trigger
public static void main(String[] args) {
// TODO Auto-generated method stub
SingletonA a = SingletonA.a;
System.out.println(SingletonB.x);
System.out.println(SingletonA.x);
System.out.println(SingletonA.a);
System.out.println(SingletonB.a);
}
}
public class SingletonA {
private SingletonA(){}
static int x = 0;
static{
x = 5;
}
static final SingletonB b = SingletonB.b;
static final SingletonA a = new SingletonA();
}
public class SingletonB {
private SingletonB(){}
static final SingletonA a = SingletonA.a;
static int x = SingletonA.x;
static final SingletonB b = new SingletonB();
}
public class Classloader {
public Classloader() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SingletonA a = SingletonA.a;
System.out.println(SingletonB.x);
System.out.println(SingletonA.x);
System.out.println(SingletonA.a);
System.out.println(SingletonB.a);
}
}
在调用 SingletonA a = SingletonA.a; 的时候 就完成了类加载step 1 、2、3
这里 主要讲step3.
prepare : 当一个类 加载自己的时候 完成step1 和 step2,就会进行prepare
如果 A extend B 那么会先prepare B的数据
prepare是 设置所有静态变量的值(全局变量),无论 static 块 还是 static 变量,都是按代码在文中的上下顺序初始化(refer to http://blog.csdn.net/teaey/article/details/22317989)
遇到 static Object o = new Object(); 也会去先初始化 该类,只要是static 都会被初始化出来,简直势如破竹
另外当一个类A 被加载(prepare)到一半的时候,遇到了其他类B的加载,其他类B的加载中又有static A a = new A();
那么这里会直接调用 A的构造方法,哪怕A 中间还有需要static变量未被prepare 完成。
eg 代码例子
public class Classloader {
public Classloader() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = Child.a;
// SingletonA a = SingletonA.a;
// System.out.println(SingletonB.x);
// System.out.println(SingletonA.x);
// System.out.println(SingletonA.a);
// System.out.println(SingletonB.a);
}
}
class Child extends Father {
static {
System.out.println("child static");
}
static int a = 1;
static Father f = new Father();
static {
System.out
.println("child's no block static due to be called init above line:static Father f = new Father();");
}
public Child() {
System.out.println("child init");
}
}
class Father {
static {
System.out.println("father static");
}
static Child c = new Child();
public Father() {
System.out.println("father init");
}
}
result output:
father static
father init
child init
child static
father init
child's no block static due to be called init above line:static Father f = new Father();