Class.forName()如何工作?

Son*_*RTh 54 java jdbc

我刚学会了java.sql package.它用于Class.forName()动态加载扩展的驱动程序DriverManager.然后我们使用DriverManager.getConnection()方法获得连接.

那么整个过程如何运作?
DriverManager类如何在不使用实际驱动程序的类名的情况下知道如何获取连接.

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

Jon*_*eet 66

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

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

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

您正在讨论的所有其余过程都是特定于JDBC的.驱动程序 - 它实现Driver,不扩展DriverManager- 只是使用注册一个适当的实例DriverManager.registerDriver.然后,当DriverManager需要为特定连接字符串找到驱动程序时,它connect依次调用每个已注册的驱动程序,直到有人说"是的,我可以成为该连接的驱动程序".

请注意,这种注册驱动程序的方式相当老套 - 查看文档以DriverManager获取更现代的数据源获取方式.

  • @Jon很好的例子,但``class.forName("com.mysql.jdbc.Driver")的`com.mysql.jdbc.Driver`类在哪里;`我试图`导入com.mysql.jdbc.Driver`仍然没有用 (2认同)
  • @UnKnown:它在MySQL jar文件中.但是你不需要导入它 - 你通常让JDBC直接初始化它,你只需要在代码中引用JDBC类. (2认同)

Shu*_*rma 20

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

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

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

如果未定义默认构造函数,那么我们必须使用反射API调用defiend构造函数.

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

Class.forName()inturn将调用调用者ClassLoader的loadClass方法(调用where的类的ClassLoder Class.forName).

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

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

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

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver();
DriverManager.registerDriver(drv);
Run Code Online (Sandbox Code Playgroud)


Boz*_*zho 16

Class.forName(..)加载并初始化目标类.这反过来意味着调用静态初始化程序块(代码定义为static { .. }.

例如,如果你看一下MySQL的驱动程序,那个驱动程序就会在那个静态块中注册自己: DriverManager.registerDriver(new Driver());

Class.forName(..)如果你能"负担"MySQL驱动程序的编译时依赖性,你可以省略并自己注册驱动程序.

也就是说,用于Class.forName(..)从应用程序初始化类很少是相关的,因为编译时依赖性不是问题.

另请注意,从版本4开始,JDBC Class.forName(..) 不再需要.通过使用服务提供程序机制,您可以指示驱动程序管理器由系统属性加载的内容.