转载请注明出处:jiq•钦's technical Blog
从下面代码可以看出来几点:
1、 class文件的加载的时机
显示加载:
调用ClassLoader.loadClass(className)与Class.forName(className)
隐式加载:
创建类对象
使用类的静态域
创建子类对象
使用子类的静态域
注意其实还有其他特殊的隐式加载:
在JVM启动时,BootStrapLoader会加载一些JVM自身运行所需的class
在JVM启动时,ExtClassLoader会加载指定目录下一些特殊的class
在JVM启动时,AppClassLoader会加载classpath路径下的class,以及main函数所在的类的class文件。
2、 两种显示加载class文件到JVM的区别
Class.forName(className)加载class的同时会初始化静态域
ClassLoader.loadClass(className)则不会初始化静态域
Class.forName借助当前调用者的class的ClassLoader完成class的加载。
3、 class文件的隐式加载会执行static域
4、 JVM默认的ClassLoader是AppClassLoader
package jiq.basic; class SuperClass { public static int i = 0; public static void func(){} static {System.out.println("静态区域被执行!");} } class SubClass extends SuperClass { public static int j = 0; } public class Test { //仅仅只是作为参数或者变量出现不会载入对应的class文件 SuperClass cc1 = null; public static void TestClassLoader(SuperClass vv) throws ClassNotFoundException { /** * 显示载入class并初始化静态域 * 将打印:静态区域被执行! */ Class.forName("jiq.basic.SuperClass"); /** * 隐式载入class并初始化静态域 * 将打印:静态区域被执行! */ SuperClass c = new SuperClass(); //使用关键字new创建对象 SuperClass.i = 9; //使用类的静态字段 SuperClass.func(); //使用类的静态方法 new SubClass(); //使用关键字new创建子类对象 SubClass.j = 10; //使用子类的静态域 /** * 仅仅只是作为参数或者变量出现不会载入对应的class文件 * 不会打印:静态区域被执行! */ SuperClass cc = vv; SuperClass array[] = new SuperClass[5]; /** * 调用ClassLoader的loadClass方法只会加载class文件到JVM * 并不会初始化静态区域,这就是ClassLoader.loadClass与Class.forName的区别 * 不会打印:静态区域被执行! */ ClassLoader.getSystemClassLoader().loadClass("jiq.basic.SuperClass"); /** * 输出为sun.misc.Launcher$AppClassLoader@2d74e4b3 * 可以看出JVM默认的类加载器ClassLoader是AppClassLoader * 而BootStrapClassLoader和ExtClassLoader都是相对较为特殊的ClassLoader */ System.out.println(ClassLoader.getSystemClassLoader()); } public static void main(String[] args) throws ClassNotFoundException { TestClassLoader(null); } }