Java中forName和loadClass的区别

问题描述

在JDBC编程中,经常会看到Class.forName(“com.mysql.jdbc.Driver”),加载数据库驱动类,当时在java中还有一种加载类的方法即getClass.getClassLoader().loadClass(“com.mysql.jdbc.Driver”),但是当我使用此方法加载数据库驱动类时,发现无法成功加载。因此觉得这两个方法应该是有些区别的。这里就比较一下二者的区别。在讲区别之前,我觉得应该先整理一下类的加载过程。

类的加载过程

Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三个步骤。除了解析外,其他步骤是严格按照顺序完成的,各个步骤的主要工作如下:
装载: 查找和导入类或接口的二进制数据;
链接: 执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
校验: 检查导入类或接口的二进制数据的正确性;
准备: 给类的静态变量分配并初始化存储空间;(注意是静态变量,类的实例变量是要等到你新建此类的对象时,才进行分配内存和初始化)
解析: 将符号引用转成直接引用;
初始化: 先运行静态代码块,之后进行静态变量的初始化;

两者区别

Class.forName(className),其实调用的方法是Class.forName(className,true,classloader);注意第二个boolean参数,它表示在装载类之后必须初始化。而看下我们上一节讲的JVM加载类的知识,我们可以看到执行过此方法后,目标对象的static块代码已经被执行,static参数也已经被初始化了
而ClassLoader.loadClass(className)方法,其实调用的方法是ClassLoader.loadClass(className,false);第二个boolean参数表示目标类被装载后不进行链接,这也就意味着不会去执行该类静态块中的内容了。因此二者的区别就显而易见了。
回到我们最初的问题,为什么用ClassLoader.loadClass(className)方法加载数据库驱动类就不行呢?打开com.mysql.jdbc.Driver的源代码,其中的static块代码如下:

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、付费专栏及课程。

余额充值