ClassLoader.loadClass()与Class.forName()的区别

ClassLoader.loadClass()与Class.forName()大家都知道是反射用来构造类的方法,但是他们的用法还是有一定区别的。在讲区别之前,我觉得很有必要把类的加载过程在此整理一下。

类的加载过程

在java中,类装载器把一个类装入java虚拟机中,要经过三个步骤来完成:装载、链接、初始化。其中,链接又可以分为校验、准备和解析三步,除了解析之外,其他步骤是严格按照顺序完成的,各个步骤的主要工作如下:

装载:查找和导入类或接口的二进制数据
链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的
校验:检查导入类或接口的二进制数据的正确性
准备:给类的静态变量分配并初始化存储空间
解析:将符号引用转成直接引用
初始化:激活类的静态变量的初始化java代码和静态java代码块

区别

  1. Class.forName(className)
    Class.forName(className)方法,实际上调用的是Class.forName(className, true, classloder),第二个参数boolean,表示的意思是,在loadClass后必须初始化。比较下前面的JVM加载类的知识,可以清晰的看到在执行过此方法后,目标对象的static块代码已经被执行,static参数也已经被初始化。
    Class.forName(className, initialize, loader)带参函数可控制是否加载static块,并且只有调用了newInstance()方法才会调用构造函数,创建类的对象。
  2. ClassLoder.loadClass(className)
    ClassLoder.loadclass(className)方法,实际上调用的是ClassLoder.loadClass(className, false),第二个参数boolean,表示目标对象在被装载后不进行链接,这就意味着不会去执行该类静态块中间的内容
    只有在newInstance才会去执行static块。因此两者的区别就显而易见了

newInstance和new区别

newInstance:弱类型。低效率,只能调用无参构造
new:强类型。相对高效,能调用任何public构造

例如:在JDBC中,常看到这样的用法,Class.forName(“com.mysql.jdbc.Driver”),如果换成了getClass().getClassLoder().loadClass(“com.mysql.jdbc.Driver”),就不行。
打开com.mysql.jdbc.Driver的源码看看:

//
// Register ourselves with the DriverManager
//
static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}

Driver在static块中会注册自己到java.sql.DriverManager,而static块就是在Class的初始化中被执行,所以这个地方只能用Class.forName(className)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值