【问题标题】:Better understaning - Class.forName("com.mysql.jdbc.Driver").newInstance ();更好的理解——Class.forName("com.mysql.jdbc.Driver").newInstance();
【发布时间】:2023-03-14 12:58:01
【问题描述】:

我遇到了this helpful link with code,它在更新以打击我的网络服务器时效果很好。我什么都能做。

现在,我唯一不完全理解的是Class.forName()。

为什么要使用它?这可以做不同的吗?这是解决其他问题的方法吗?添加参考?创建一个类作为实现/扩展另一个类?

我想完全了解发生了什么,但这是我的方式。

谢谢

【问题讨论】:

  • 你看过forName()类java.lang.Class中方法的API文档吗?

标签: java mysql


【解决方案1】:

该代码强制表示 MySQL 驱动程序的类加载和初始化。在Java 中,除非必要 类被加载,否则不会加载一个类。由于 JDBC 代码通常从不直接引用驱动程序,因此如果没有 Class.forName(或其他一些等效替代方案),它将不会被加载。

请注意,load 和 initialize 类都是必要的,这是两个不同的事情。

另外,请注意,不必调用.newInstance()——驱动程序的静态初始化程序已经将自己注册为 JDBC 驱动程序。

最后,请注意,使用 Service Loader API 通常不需要调用 Class.forName() 来加载驱动程序:它可以自动加载。

【讨论】:

  • 所以这可以在我的代码中代表驱动程序的多个类上连续调用,而不会产生我假设的后果?但为什么要这样做呢?我想这是我真正的问题。有没有更永久的(在项目中添加参考等)方法来做到这一点?
  • 您必须添加对库的引用才能使其工作。这样做是为了将驱动程序与您的代码分离,因为假设您以后可能想要替换数据库和驱动程序。
  • 有关类加载/初始化的更多信息,请查看this answer
  • 只是补充一点.newInstance()实际上是需要的,因为一些JDBC Drivers不遵循规范,并且不会在静态初始化期间注册自己,而是在实例化期间。关于“通常不需要调用 Class.forName”这一事实:如果您使用的是 JDBC 4 或 4.1,则没有必要,Driver 供应商正确地完成了它的工作。如果您使用的是 JDBC3,或者供应商未在 META-INF/services/java.sql.Driver 中提供 Driver 的类名,则必须这样做。
【解决方案2】:

您可以使用例如:

import com.mysql.jdbc.Driver;

public class MyClass {
   //[...]
   public void myMethod() {
        Class<Driver> clz = Driver.class;
        Driver driver = clz.newInstance();
   }
}

但这不是那么灵活;例如,您可以从配置文件中读取名称“com.mysql.jdbc.Driver”。也许您想使用其他驱动程序(来自 Oracle)并且您不想更改代码;按照上面介绍的方式,这是不可能的,所以正确的方法是使用Class.forName(name)。

【讨论】:

    【解决方案3】:

    所有 JDBC 驱动程序都有一个静态块,它向 DriverManager 注册自身,而 DriverManager 仅具有静态初始化程序。

    MySQL JDBC 驱动程序有一个静态初始化器,如下所示:

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

    JVM 执行静态块,Driver 将自己注册到 DriverManager。 您需要一个数据库连接来操作数据库。为了创建与数据库的连接,DriverManager 类必须知道您要使用哪个数据库驱动程序。它通过遍历已注册的驱动程序数组(内部是一个 Vector)并在数组中的每个驱动程序上调用 acceptURL(url) 方法来实现这一点,有效地要求驱动程序告诉它它是否可以处理 JDBC网址。

    【讨论】:

      【解决方案4】:

      Class.forName(className) 加载具有指定className 的类。

      JDBC 驱动程序以这种方式加载以避免编译时依赖于特定的 JDBC 驱动程序。这个想法是您使用 Java 的 JDBC API(在包 java.sql 和 javax.sql 中定义的类和接口),而无需直接引用特定的 JDBC 驱动程序。

      当您通过forName 调用让Java 加载驱动程序类时,驱动程序将自行注册以便使用。

      请注意,对于大多数 JDBC 驱动程序,不需要显式创建驱动程序类的新实例;您可以停止拨打.newInstance()。

      请注意,自 JDBC 4.0 版以来,不再需要调用 Class.forName() - 发现驱动程序的过程已得到改进,JDBC 可以自动加载它们。

      【讨论】:

        猜你喜欢
        • 2013-10-25
        • 2013-02-08
        • 2023-04-06
        • 1970-01-01
        • 2011-06-06
        • 2015-05-18
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多