最近阅读别人代码遇到了ClassLoader.loadClass(String name)
,印象中常用的是Class.forName(String name)
,所以查阅了资料将二者的区别记录一下~~~
说到这两个方法,就不得不提到java中反射
的概念:
反射的基本概念:程序可以访问、检测和修改其本身状态或行为的一种能力。
反射机制是java的特性之一,指的是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取它所有的成员变量和方法并且显示出来,这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
有了对反射的基本概念的认知,那我们回到上面要探讨的问题,为什么要把ClassLoader.loadClass(String name)和Class.forName(String name)进行比较呢,因为他们都能在运行时对任意一个类,都能够知道该类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。
在比较它俩之前需先了解一下java类装载
的过程:
1、加载
Jvm把class文件字节码加载到内存中,并将这些静态数据转换成运行时数据区中方法区的类型数据,在运行时数据区堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。
2、链接
执行下面的校验、准备和解析步骤,其中解析步骤是可选的
a:校验:检查加载的class文件的正确性和安全性
b:准备:为类变量分配存储空间并设置类变量初始值,类变量随类型信息存放在方法区中,生命周期很长,使用不当和容易造成内存泄漏。
c:解析:jvm将常量池内的符号引用转换为直接引用
3、初始化:
执行类变量赋值和静态代码块
了解完类装载的过程我们继续来比较二者的区别:
Classloder.loaderClass(String name)
内部调用:Classloder. loadClass(name, false)
方法:Classloder. loadClass(String name, boolean resolve)
1:参数name代表类的全限定类名
2:参数resolve代表是否解析
,resolve为true是解析该类Class.forName(String name)
内部调用:Class.forName(className,true,ClassLoader.getClassLoader(caller))
方法:
Class.forName0(String name, boolean initialize, ClassLoader loader)
1:参数name代表全限定类名
2:参数initialize表示是否初始化该类
,为true是初始化该类
3:参数loader 对应的类加载器
区别:
Class.forName得到的class是已经初始化完成的
Classloder.loaderClass得到的class是还没有链接的
使用:
有些情况是只需要知道这个类的存在而不需要初始化的情况使用Classloder.loaderClass,而有些时候又必须执行初始化就选择Class.forName