1、类从CLASS文件被加载到JVM中,整个生命周期:
加载、检验、准备、解析、初始化、使用、卸载
连接(linking):检验、准备、解析
其中:固定的顺序有:加载、检验、准备、初始化、卸载。
解析在某些情况下会在初始化之后再进行(这是为了支持Java的动态绑定或晚期绑定)
2、触发类初始化(有且只有这几种情况)(加载、检验、准备在初始化之前执行)
1)new 对象
2)访问静态变量
3)访问静态方法
4)初始化一个类时候,如果发现父类还没初始化,则先初始化父类
5)使用java.lang.reflect包的方法对类进行反射的时候
6)虚拟机启动,需要执行一个类(包含main函数)
3、被动引用(被动使用类字段)不会触发类的初始化
1)子类引用父类的字段,只会触发父类的初始化,不会触发子类的初始化
public class SuperClass {
static{
System.out.println("父类加载。。。。。。");
}
protected static int value=123;
}
public class SonClass extends SuperClass{
static {
System.out.println("子类加载------");
}
}
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println(SonClass.value);
}
}
日志打印:
父类加载。。。。。。
123
2)通过数组定义来引用,不会触发类的初始化
public class ClassLoadTest {
public static void main(String[] args) {
SuperClass[] array=new SuperClass[10];
}
}
无日志打印
3)常量(final static修饰)在编译期的时候,会存入常量池中,不会触发定义常量的类的初始化。