Java中String.class.getClassLoader().loadClass() 与Class.forName()的区别

最近阅读别人代码遇到了ClassLoader.loadClass(String name),印象中常用的是Class.forName(String name),所以查阅了资料将二者的区别记录一下~~~
说到这两个方法,就不得不提到java中反射的概念:

反射的基本概念:程序可以访问、检测和修改其本身状态或行为的一种能力。

反射机制是java的特性之一,指的是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取它所有的成员变量和方法并且显示出来,这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

有了对反射的基本概念的认知,那我们回到上面要探讨的问题,为什么要把ClassLoader.loadClass(String name)和Class.forName(String name)进行比较呢,因为他们都能在运行时对任意一个类,都能够知道该类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。
在比较它俩之前需先了解一下java类装载的过程:

Java中String.class.getClassLoader().loadClass() 与Class.forName()的区别_第1张图片
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

你可能感兴趣的:(Java中String.class.getClassLoader().loadClass() 与Class.forName()的区别)