欢迎您光临本小站。希望您在这里可以找到自己想要的信息。。。

ClassLoader.loadClass 和Class.forName的区别

java water 2139℃ 0评论

前言

在讨论之前,首先要明白一个Java类加载到JVM中经过的三个步骤

  • 装载: 查找和导入类或接口的二进制数据

  • 链接: 分别执行 校验,准备,和解析

  • 校验: 检查导入类或接口的二进制数据的正确性;

  • 准备: **给类的静态变量分配并初始化存储空间; **

  • 解析: 将符号引用转成直接引用;

  • 初始化: 激活类的静态变量的初始化Java代码和静态Java代码块。

两者的区别

对于Class.forName方法来说

   public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)

三个参数的含义分别是

  • name: 要加载Class的名字

  • initialize: 是否要初始化

  • loader : 指定的classLoader

对于 ClassLoader.loadClass()

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException

这个方法的两个参数

  • name : class的名字

  • resolve : 是否要进行链接

所以: 通过传入的参数可以知道,Class.forName 执行之后已经对 被加载类的静态变量分配完毕了存储空间,而classLoader.loadClass 并没有一定执行完 链接这一步.

使用的区别

当你想动态加载一个类,而这个类又存在静态代码块或者静态变量,而你在加载的时候就想同时初始化这些静态代码块。这个时候你可能更应该偏向于使用Class.forName

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
........................省略代码....................

可以看一个使用,这是一个用户在吗,命令行调用jdbc时的启动入口

 public static void main(String[] args) throws Exception {
        String jdbcUrl = DEFAULT_URL;

        if ((args.length == 1) && (args[0] != null)) {
            jdbcUrl = args[0];
        }
      //可以看到这里是使用了Class.forName 方法而不是 Classloader.forName()
        Class.forName("com.mysql.jdbc.Driver").newInstance();
`.....

一些小的细节

  • ClassLoader.forName方法如果穿入的Classloader对象为null是不会抛出空指针异常的,而是选择使用Bootstrap ClassLoader去加载,但是我们知道Bootstrap只加载java core 库。 so….

作者:walker_liu_fei
链接:https://www.jianshu.com/p/50e18a563301
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载请注明:学时网 » ClassLoader.loadClass 和Class.forName的区别

喜欢 (0)or分享 (0)

您必须 登录 才能发表评论!