这段代码的作用是动态加载MySQL数据库的驱动程序,并创建一个驱动程序的实例对象。

21
连接到MySQL数据库时,我按照以下步骤进行操作。
Connection con = null;
Resultset rs = null;
Statement st = null;
Class.forName("com.mysql.jdbc.Driver").newInstance();
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/database","root","passwp");
实际上,我想知道Class.forName("com.mysql.jdbc.Driver").newInstance();语句是做什么的。 尽管这个类不在mysql.jar中。它在哪里呢?

请注意,问题中的代码存在缺陷:人们不应该复制它。 - undefined
6个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
24

Class类位于java.lang包中,因此它随Java一起分发,并自动导入每个类。

forName()方法的作用是返回由类加载器加载的参数的Class对象。然后,newInstance()方法返回该类的新实例。

因此,当您调用Class.forName(...)时,它将返回com.mysql.jdbc.Driver.class。然后,您在该类上调用newInstance(),它将返回一个没有参数的类实例,因此它基本上相当于调用new com.mysql.jdbc.Driver();


没问题,Class/类的东西可能有点难以理解。 :) - chossenger
2
我点了踩,因为虽然这个回答在技术上是正确的,但它并没有帮助我们理解为什么要在使用jdbc连接的上下文中使用这段代码。它也没有提到这行代码已经不再必要。Koray的回答更有意义,也更加实时。 - user1884155
它还没有提到,对于Connector/J 8.0及更高版本的驱动程序,该类名已被弃用(尽管它目前仍然可用)。 - undefined

13

引用自 JDBC规范,第9章,第2节:

JDBC驱动程序必须实现Driver接口,并且该实现必须包含一个静态初始化器,当加载驱动程序时将调用此初始化器。此初始化器通过DriverManager向其注册新的实例。

以下是AcmeJdbcDriver的示例代码:

public class AcmeJdbcDriver implements java.sql.Driver {
    static {
        java.sql.DriverManager.registerDriver(newAcmeJdbcDriver());
    }
}

当您调用 Class.forName(String className) 时,根据API文档,会发生以下情况:

调用 forName("X") 会导致名为 X 的类被初始化。

其中初始化涉及执行静态块中的代码。

因此,基本上您初始化了 Driver 类,并且按照JDBC规范,该类会向 java.sql.DriverManager 注册自身。

请注意,这不再需要。详情请参见 此处

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry:

my.sql.Driver

Applications no longer need to explictly load JDBC drivers using Class.forName().


3
这是一个更好的解释!谢谢你! - Aleksandar
1
因为他是唯一提到应用程序不再需要调用Class.forName(..)的人,所以他被提升了。 - Brent Sandstrom

6

如果在类路径中找到"com.mysql.jdbc.Driver"类,则会初始化该类,这意味着由于注册过程在驱动程序类的静态初始化器中,因此驱动程序已在JDBC驱动程序管理器中注册...

还有另一种方法可以使用静态DriverManager.registerDriver()方法来注册驱动程序。


forName方法是做什么的? - user2098012
调用forName("com.mysql.jdbc.Driver")会导致名为Driver的类被初始化。 - aleroot
我有另一个问题,事实上我忘记了我的MySQL密码,并且我已经查看了关于更改MySQL密码的所有SO答案,但我无法找回它。 请问你能帮我吗? - user2098012
@javaL 看这里:http://dev.mysql.com/doc/refman/5.0/en/resetting-permissions.html - aleroot
您说要使用 DriverManager.registerDriver,请问能否发布完整的代码? - user2098012
@javaL 我说过你甚至可以使用DriverManager.registerDriver,但是使用Class.forName也没有任何问题... - aleroot

5
它会创建一个com.mysql.jdbc.Driver类的新实例,因此调用静态初始化程序,该程序将在DriverManager中注册驱动程序,因此您可以基于第二行中使用的URL创建mysql连接。但是,该类应该在mysql.jar中。

2
您无需创建实例即可运行静态块。 - Koray Tugay

2
正如所指出的,问题中的代码存在缺陷。以下是其中的问题。 主要问题:
  • 你不需要调用Class.forName来加载或初始化JDBC驱动程序。 DriverManager.getConnection(...)调用将自动完成所有这些工作。 自从JDBC 4.0 / Java 6以来,Class.forName的东西就变得多余了。

    DriverManager.getConnection(...)将根据JDBC URL前缀选择一个JDBC驱动程序。 它知道如何在类路径中搜索合适的驱动程序,加载驱动程序类并触发初始化以使其注册。

  • 你不需要调用newInstance()来触发类初始化。 实际上,你所做的只是创建一个不必要的Driver类的实例。 而且(我认为)会添加额外的需要处理的已检查异常。

  • 该JDBC驱动程序的类名已被弃用。 从MySQL Connector/J 8.0和8.1开始,类名为com.mysql.cj.jdbc.Driver。(旧的com.mysql.jdbc.Driver类名仍然有效,但会产生运行时警告。)

    再次强调,DriverManager会处理这个。 你不需要知道驱动程序的类名。

小问题:

  • forNamenewInstance会抛出一些需要处理的已检查异常。

  • 将账户名和密码直接写入代码是一个糟糕的主意,即使你不打算公开你的代码。

大部分这些问题最好的解决方法是删除这行代码:

Class.forName("com.mysql.jdbc.Driver").newInstance();
即OP所询问的那行代码!

-1
它创建了com.mysql.jdbc.Driver类的一个新实例并注册了驱动程序。 因此,如果您调用Class.forName("com.mysql.jdbc.Driver")而没有使用'newInstance()',它将仅返回com.mysql.jdbc.Driver类并注册驱动程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,