1.当虚拟机启动时,加载用户指定的main方法所在的类。
2.当在main方法遇到了new关键字时,初始化new指令的目标类。
3.当遇到静态方法调用时,初始化静态方法所在的类。
4.当遇到静态变量调用时,初始化静态变量所在的类。
5.子类的初始化时会先触发父类的初始化。
6.使用反射调用某个类时,会初始化该类。
7.如果一个类直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化。
注意
1.当子类去引用父类的静态变量时,父类会被加载,子类不会。
2.会先初始化main方法所在的类
3.当用数组创建类是并不会初始化该类,但是会将该类加载进内存。
4.如果去调用一个类中static final修饰的常量则不会加载该类,而是直接从常量池中将常量取出。
测试:
执行class文件时,可以通过JVM参数 -verbose:class 查看类加载的先后顺序。
测试第一条和第二条。
public class TestClassLoader{
public static void main(String[] args){
Demo1 demo1 = new Demo1();
}
}
public class Demo1{
}
测试第三条。
public class TestClassLoader{
public static void main(String[] args){
Demo1.method();
}
}
public class Demo1{
public static void method(){
}
}
第四条跟第三条差不多就不测试了。
测试第五条,会先初始化父类,在初始化子类。
public class TestClassLoader extends Parent{
public static void main(String[] args){
}
}
public class Parent {
}
测试第6条。
public class TestClassLoader{
public static void main(String[] args){
try{
//注意,要先将Demo1编译为class文件才能调用到!
Class clazz = Class.forName("Demo1");
}catch(ClassNotFoundException e){
}
}
}
测试第7条,先初始化实现的接口。