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

新手上路,请多包涵

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

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

原文由 Johanna 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 590
2 个回答

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

 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) 返回 Class 与具有给定字符串名称的类或接口关联的对象, 即它返回 test.Demo.class clazz 变量类型 Class

然后,调用 clazz.newInstance() 创建由这个 Class 对象表示的类的新实例。该类被实例化,就好像是通过带有空参数列表的 new 表达式一样。 换句话说,这实际上相当于 new Demo() 并返回 Demo 的新实例。

运行这个 Demo 类会打印以下输出:

 Hi!

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

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

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

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

(…) A 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 增强功能

原文由 Pascal Thivent 发布,翻译遵循 CC BY-SA 4.0 许可协议

Class.forName() 为您提供类对象,这对反射很有用。该对象具有的方法是由 Java 定义的,而不是由编写该类的程序员定义的。每个班级都一样。调用 newInstance() 给你那个类的一个实例(即调用 Class.forName("ExampleClass").newInstance() 它相当于调用 new ExampleClass() ),你可以调用类定义的方法,访问可见域等

原文由 Thomas Lötzer 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题