Class.forName() vs ClassLoader.loadClass() - 哪个用于动态加载?

2022-08-31 10:10:57

动态装入类时,何时适合使用

Class.forName("SomeClass");

以及何时应使用

ClassLoader.getSystemClassLoader().loadClass("SomeClass");

或者,它们是做同一件事的两种方式吗?


答案 1

他们是完全不同的!

Class.forName(String) 的文档所述,

返回与具有给定字符串名称的类或接口关联的 Class 对象。调用此方法等效于:Class.forName(className, true, currentLoader)

(true这里指的是你想初始化类吗?)

另一方面,ClassLoader.loadClass(String)

调用此方法等效于调用 。loadClass(name, false)

(在这里,布尔值与初始化无关;但是如果您检查loadClass(String,boolean)文档,您会发现它所做的只是加载类,而不是初始化它)。

第一个 () 将:Class.forName("SomeClass");

  • 使用类装入器来装入调用此代码的类
  • 初始化类(即,将运行所有静态初始值设定项)

另一个 () 将:ClassLoader.getSystemClassLoader().loadClass("SomeClass");

  • 使用“system”类装入器(可重写))
  • 不初始化类(例如,如果您使用它来加载 JDBC 驱动程序,则不会注册该类,并且您将无法使用 JDBC!

假设您正在编写一个将在容器(如 Tomcat)上执行的 Web 应用程序。Tomcat 所做的是为每个 Web 应用程序创建一个类装入器(以便它以后可以卸载 webapp 并释放内存 - 您需要一个专用的类装入器才能使其工作!在这种情况下,您可以看到两个调用将产生完全不同的结果!

有关类装入和初始化的更详细(和权威)信息,请查看 Java 语言规范最新(第 3 版)的第 12.2 和 12.4 节。


答案 2

Class.forName()使用调用方的类装入器并初始化类(运行静态初始化器等)

loadClass是一个方法,因此它使用显式提供的加载程序,并懒惰地初始化类(首次使用时)。ClassLoader

请注意,有一个 Class.forName() 也接受 .ClassLoader


推荐