一尘不染

Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?

java

Class.forName()和之间有什么区别Class.forName().newInstance()

我不了解其中的重大区别(我已经阅读了一些有关它们的信息!)。请你帮助我好吗?


阅读 401

收藏
2020-03-04

共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中所述,调用将返回与具有给定字符串名称的类或接口关联的对象,即它返回受type变量影响的对象。Class.forName(String) Classtest.Demo.classclazzClass

然后,调用创建该 对象表示的类的新实例。就像通过带有空参数列表的表达式实例化该类。换句话说,这实际上等于a 并返回的新实例。clazz.newInstance() Classnewnew Demo()Demo

Demo因此,运行此类将输出以下输出:

Hi!

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

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

实际上,如果你想走得更远,请看一下Ted Neward的论文《理解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驱动程序的结果。

2020-03-04