探讨Class.forName与ClassLoader.loadClass与new Object

探讨Class.forName与ClassLoader.loadClass与new Object

  • 探讨ClassforName与ClassLoaderloadClass与new Object
    • 实例展示
      • TestObject对象
      • TestDriver测试
      • 测试结果
    • 理论谈论
    • 扩展
    • ClassforName与new Object

实例展示

TestObject对象

public class TestObject {

    static {
        System.out.println("我已经成功初始化。");
    }

}

TestDriver测试

public class TestDriver {

    public static void main(String[] args) {
        try {
            //1. 使用Class.forName加载
            //Class.forName(TestObject.class.getName());


            //2. 使用loader.load加载
            ClassLoader loader=TestDriver.class.getClassLoader();
            loader.loadClass(TestObject.class.getName());

            //3. 使用new Object
            //TestObject object=new TestObject();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

测试结果

1.使用Class.forName加载
输出:我已经成功初始化。

2.使用loader.load加载
没有任何输出

3.使用new Object
输出:我已经成功初始化。

理论谈论

我们知道Java在加载的过程将经过这么几个步骤。

从上面的结果,我们可以看出,其实Class.forName与new Object的方法已经完成了类的初始化,但是ClassLoader.loadClass只是完成了类的加载。之所以要加载类是因为JVM并不是在项目运行时就把所有的类文件加载到JVM,而是当类需要的的时候,才去加载。
加载就是通过类的全限定名获取二进制字节流,将二进制字节流转成方法区中运行的数据结构,在内存中生成Java.lang.class对象。

Class.forName(className)法实际上调用的方法是Class.forName0(className, true, ClassLoader.getClassLoader(caller), caller),第二个参数boolean代表类是否需要被初始化。

ClassLoader.loadClass(className)方法实际上调用的方法是ClassLoader.loadClass(name, false),第二个参数boolean代表的是类是否进行链接。

从上面可以看出,ClassLoader.loadClass(className)默认是不链接的,意味着,静态方法将无法被执行。

扩展

我们第一次认识Class.forName,可能是在写数据库连接的时候。那时候,我就按照教程写,很轻松就拿到了连接。
现在,我们来分析一下JDBC驱动装载过程:
当我们写
Class.forName(“com.MySQL.jdbc.Driver”);
com.MySQL.jdbc.Driver将被初始化,这时候,调用了com.MySQL.jdbc.Driver静态初始化块

static {
    try {
        DriverManager.registerDriver(new Driver());
    } catch (SQLException var1) {
        throw new RuntimeException("Can\'t register driver!");
    }
}

向DriverManager注册了这个驱动。

public static synchronized void registerDriver(java.sql.Driver driver,
            DriverAction da)
        throws SQLException {

        /* Register the driver if it has not already been added to our list */
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }

        println("registerDriver: " + driver);

    }

驱动被添加到了registeredDrivers。
综上,不能使用ClassLoader.loadClass。

Class.forName与new Object

这两者的区别就是new Object可以构造带参构造器。

你可能感兴趣的:(Java)