Class.forName(Driver.class)
Posted
技术标签:
【中文标题】Class.forName(Driver.class)【英文标题】: 【发布时间】:2016-01-13 09:36:40 【问题描述】:在建立数据库连接的上下文中,我们通常导入所需的包并使用 Class.forName() 通过调用类的类加载器加载所需的驱动程序类。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
....
....
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection(...);
我们不能像这样简单地删除 Class.forName():-
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.mysql.jdbc.*;
....
....
Connection con=DriverManager.getConnection(...);
我的问题是,当一个类的依赖项由加载依赖类的同一个类加载器加载时,通过与 Class.forName(className) 隐式使用的相同机制,为什么要给 Class .forName() 明确。只需在 import 语句中包含驱动程序类。 驱动程序类在遇到 DriverManager.getConnection() 行时不会自动加载吗? com.mysql.jdbc 包在 import 语句中。 还是我需要像
这样添加一行Class clazz=com.mysq.jdbc.Driver.class
触发 Class.forName() 。
【问题讨论】:
【参考方案1】:首先,不再需要加载驱动程序类,因为 Java 有一个内置的服务提供程序加载机制,它会在类路径中的 jar 文件中查找可用的驱动程序。
仅仅导入一个类并不足以加载它。导入所做的只是允许您在编译时使用其简单名称而不是其完全限定名称来引用该类。但是如果你从来没有真正加载过这个类,它就什么也做不了。
您确实可以在不使用反射的情况下加载类,但这意味着您需要将驱动程序作为编译时依赖项,这通常是不需要的:您不应该依赖驱动程序中特定于数据库的类,而是仅在标准 JDBC 接口上。在编译类路径中没有驱动程序可以确保这一点。
【讨论】:
“不再需要加载驱动程序类”。不过,我从未见过那种作品。 :-( 仅当驱动程序 JAR 文件位于系统类路径上时才有效(而不是动态加载的东西)? 我想是的。我几乎从不使用DriverManager,而且总是通过连接池,所以我没有太多具体的经验。【参考方案2】:import
语句在运行时不执行任何操作。它甚至不是编译类的一部分。它只是告诉编译器在哪里寻找东西。
像Class<?> dummy = com.mysql.jdbc.Driver.class
这样的行可以工作,但是你对 MySQL 驱动程序 JAR 文件有一个编译时依赖(Class.forName 没有,但在总体方案中可能不是坏事) .
【讨论】:
那么像“Class> dummy”这样的行如何帮助加载类?是否隐式调用 Class.forName() ?谁打电话?或者该行是否简单地被 Class.forName(com.mysql.jdbc.Driver.class) 替换,在该行下这将不再是编译时依赖? 如果你引用一个类,它将被加载。对于 JDBC 驱动程序,您只需将其注册到驱动程序管理器即可。当您在代码中引用一个类时(如new Arraylist<Integer>()
或 com.mysql.jdbc.Driver.class
),JVM 将首先自动加载该类(如果尚未加载)。【参考方案3】:
只要您的驱动程序是JDBC 4.0 兼容,您就不需要Class.forName()
。
请阅读introduction on DriverManager JavaDoc 了解如何处理。
当然,驱动程序仍然需要在类路径中。 Class.forName()
也是如此(否则会抛出 ClassNotFoundException
)
【讨论】:
以上是关于Class.forName(Driver.class)的主要内容,如果未能解决你的问题,请参考以下文章
Class.forName("Something") 和 Class.forName("Something").newInstance() 之间的区别; [复制
Class.forName() 初始化Thread.currentThread().getContextClassLoader().getResourceAsStream