Class.forName() 如何工作?

2022-08-31 16:05:04

我刚刚了解到.它用于动态加载扩展的驱动程序。然后我们使用方法获得连接。java.sql packageClass.forName()DriverManagerDriverManager.getConnection()

那么整个事情是如何工作的呢?
DriverManager 类如何知道如何在不使用实际驱动程序的类名的情况下获取连接。

我们也可以使用Class.forName()来自定义应用程序...如果用一个例子来解释这一点,我会非常高兴。


答案 1

Class.forName只需加载一个类,包括运行其静态初始值设定项,如下所示:

class Foo {
    static {
        System.out.println("Foo initializing");
    }
}

public class Test {
    public static void main(String [] args) throws Exception {
        Class.forName("Foo");
    }
}

您正在谈论的所有其他过程都是特定于JDBC的。驱动程序 - 实现 ,它不会扩展 - 只是使用 注册适当的实例。然后,当需要查找特定连接字符串的驱动程序时,它会依次调用每个已注册的驱动程序,直到其中一个成功并返回非空连接。DriverDriverManagerDriverManager.registerDriverDriverManagerconnect

请注意,这种注册驱动程序的方式是相当老式的 - 查看驱动程序管理器的文档,了解获取数据源的更现代方法。


答案 2

当我们使用new运算符创建类的instace时,它会做两件事

  1. 如果未加载该类,则将其加载到内存中 - 这意味着从.class文件创建类的内存中表示形式,以便可以从中创建实例。这包括初始化静态变量(解析该类)
  2. 创建该类的实例并存储对变量的引用。

Class.forName只做第一件事。它将类加载到内存中,并将该引用作为 Class 的实例返回。如果我们想创建一个实例,我们可以调用该类的 newInstance 方法。这将调用默认构造函数(无参数构造函数)。请注意,如果默认构造函数不可访问,则 newInstance 方法将引发 .如果该类是抽象类或接口,或者它没有默认构造函数,则它将抛出一个 .如果在解析该类的过程中出现任何异常,它将引发 .IllegalAccessExceptionInstantiationExceptionExceptionInInitializerError

如果未定义默认构造函数,则必须使用反射 API 调用 defiend 构造函数。

但 Class.forName 的主要优点是,它可以接受类名作为 String 参数。因此,我们可以动态传递类名。但是,如果我们使用new运算符创建类的实例,则类名不能动态更改。

Class.forName()inturn 将调用调用方 ClassLoader 的 loadClass 方法(从何处调用类的 ClassLoder)。Class.forName

缺省情况下,解析该类。这意味着,初始化该类内的所有静态变量。可以使用重载方法更改相同的Class.forName()Class.forName(String name,boolean initialize,ClassLoader loader)

使用加载jdbc驱动程序的主要原因是,驱动程序可以动态变化。在静态块中,所有驱动程序都将创建其自身的实例,并使用方法向 DriverManager 注册该类。由于 默认情况下解析该类,因此它将初始化静态初始值设定项。因此,当我们调用 时,驱动程序类将被加载,实例化并向DriverManager注册Class.forName()DriverManager.registerDriver()Class.forName(String className)Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver")

因此,如果您使用的是新的操作员,则必须执行以下操作。
法典:

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver();
DriverManager.registerDriver(drv);

推荐