小编典典

“Class.forName()”和“Class.forName().newInstance()”有什么区别?

all

Class.forName()和 和有什么不一样Class.forName().newInstance()

我不明白其中的显着差异(我读过一些关于它们的东西!)。请你帮助我好吗?


阅读 76

收藏
2022-08-29

共1个答案

小编典典

也许演示如何使用这两种方法的示例将帮助您更好地理解事物。因此,请考虑以下类:

package test;

public class Demo {

    public Demo() {
        System.out.println("Hi!");
    }

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("test.Demo");
        Demo demo = (Demo) clazz.newInstance();
    }
}

正如其 javadoc 中所解释的,调用 返回 与具有给定字符串名称的类或接口关联的对象,
即它返回受类型变量影响的对象。Class.forName(String)
Classtest.Demo.class``clazz``Class

然后,调用 会创建由该 对象表示的类的新实例。 类被实例化,就好像一个 带有空参数列表的表达式。 换句话说,这里实际上等价于 a并返回
的新实例。clazz.newInstance()
Class``newnew Demo()``Demo

因此,运行此类Demo会打印以下输出:

Hi!

与传统的最大区别new在于,它newInstance允许实例化一个直到运行时才知道的类,从而使您的代码更加动态。

一个典型的例子是 JDBC API,它在运行时加载执行工作所需的确切驱动程序。EJB 容器、Servlet
容器是其他很好的例子:它们使用动态运行时加载来加载和创建在运行时之前它们一无所知的组件。

实际上,如果您想更进一步,请查看 Ted Neward 的文章Understanding
Class.forName()
,我在上面的段落中进行了解释。

编辑 (回答作为评论发布的 OP 的问题):JDBC 驱动程序的情况有点特殊。正如JDBC API
入门的
DriverManager章节所述:

(…) 一个Driver类被加载,因此会DriverManager以两种方式之一自动注册到 中:

1.
通过调用方法Class.forName。这会显式加载驱动程序类。由于它不依赖于任何外部设置,因此这种加载驱动程序的方式是使用DriverManager
框架的推荐方式。以下代码加载类acme.db.Driver

>      Class.forName("acme.db.Driver");

如果acme.db.Driver已编写为加载它会导致创建一个实例并
DriverManager.registerDriver使用该实例作为参数进行
调用(正如它应该做的那样),那么它位于
DriverManager驱动程序列表中并且可用于创建连接。

  1. (…)

在这两种情况下,新加载的Driver类都有责任通过调用来注册自己DriverManager.registerDriver。如前所述,这应该在加载类时自动完成。

为了在初始化期间注册自己,JDBC 驱动程序通常使用如下静态初始化块:

package acme.db;

public class Driver {

    static {
        java.sql.DriverManager.registerDriver(new Driver());
    }

    ...
}

调用Class.forName("acme.db.Driver")会导致acme.db.Driver类的初始化,从而导致静态初始化块的执行。并且
Class.forName("acme.db.Driver")确实会“创建”一个实例,但这只是(好的)JDBC驱动程序实现方式的结果。

作为旁注,我要提到的是,JDBC 4.0(自 Java 7 起作为默认包添加)和 JDBC 4.0
驱动程序的新自动加载功能不再需要所有这些。请参阅Java SE 6 中的 JDBC 4.0
增强

2022-08-29