也许一个示例演示如何使用两种方法将有助于你更好地理解事物。因此,请考虑以下类:
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两种方式之一自动向进行注册:
- 通过调用方法
Class.forName
。这将显式加载驱动程序类。由于它不依赖任何外部设置,因此推荐使用这种加载驱动程序的方式来使用该DriverManager
框架。以下代码加载该类acme.db.Driver:
Class.forName("acme.db.Driver");
如果
acme.db.Driver编写了这样的代码以便加载它会导致创建一个实例,并且还
DriverManager.registerDriver以该实例作为参数进行调用(应该这样做),则它在
DriverManager驱动程序列表中,可用于创建连接。
(...)
在这两种情况下,新加载的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驱动程序的结果。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)