首先是上一节加载机制的补充:
如果一个类初始化,会导致该类的接口的载入但不会导致初始化
继承的话如果访问该类的父类的静态成员不会导致该类初始化
/**
* 该函数不会导致Child3初始化
* 说明需要访问属于本类而不是父类的静态成员,才能导致初始化*/
class Parent3{
static int a=6;
static {
System.out.println("parent: ");
}
static void doSomething(){
System.out.println("qqparent: ");
}
}
class Child3 extends Parent3{
static {
System.out.println("child: ");
}
}
public class test {
public static void main(String[] args) {
System.out.println(Child3.a);
System.out.println("-*---------------------");
Child3.doSomething();
}
}
加载失败会报ClassNotFoundException异常
类初始化步骤:
- 加载,链接
- 如果该类存在直接父类,且父类还没初始化,就先初始化直接父类
- 加入类中存在初始化语句,那就一次执行这些初始化语句
双亲委托机制:
当要加载一个类会先让父类尝试加载,依次向上委托,最后相当于从当前类加载器的顶层开始尝试加载,如果不行,则下派 ,直到找到可以加载该类的类加载器,如果找不到就报异常
类的加载器种类
/** * 数组类型的类加载器与该数组单个实例的类型的加载器相同 * 比如String[]类型与String类型的加载器相同*/
public class 数组类型的类加载器 {
public static void main(String[] args) {
Mytest5[]mytest5s=new Mytest5[5];
System.out.println(mytest5s.getClass().getClassLoader());
String[]strings=new String[5];
System.out.println(strings.getClass().getClassLoader());
Object[]objects=new Object[5];
System.out.println(objects.getClass().getClassLoader());
int[]ints=new int[5];
System.out.println(ints.getClass().getClassLoader());
System.out.println(int.class.getClassLoader());
Integer[]integers=new Integer[5];
System.out.println(integers.getClass().getClassLoader());
}
}
几种类加载器获取
-
获取当前线程上下文的类加载器
-
获取系统类加载器
-
获取加载该类的类加载器