转载请注明出处: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);
}
}