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

Zac*_*ack 98 java classloader

动态加载类时,何时适合使用

Class.forName("SomeClass");
Run Code Online (Sandbox Code Playgroud)

我应该什么时候使用

ClassLoader.getSystemClassLoader().loadClass("SomeClass");
Run Code Online (Sandbox Code Playgroud)

或者,他们是两种做同样事情的方式吗?

Bru*_*eis 148

他们是完全不同的!

如文档中所述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");)将:

  • 使用"系统"类加载器(可以覆盖)
  • 没有初始化类(比如,如果你使用它来加载JDBC驱动程序,它将不会被注册,你将无法使用JDBC!)

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

有关类加载和初始化的更详细(和权威)信息,请查看最新(第3版)Java语言规范的12.212.4节.

  • 我发现这很难,并且可以确定使用Catalina就是这种情况.我在`Class`类型上调用`getClassLoader().loadClass("...");`来尝试加载Torque对等类,以便运行将对等点映射到数据库表的静态初始化程序块.此调用未执行静态块.但是,在调用`Class.forName("...");`为对等类时,执行了静态块.+1给了一个很好的解释并教育我为什么遇到这个问题! (3认同)
  • +1,更多细节:) (2认同)

Dav*_*ton 8

Class.forName() 使用调用者的类加载器并初始化类(运行静态intitializers等)

loadClass是一个ClassLoader方法,因此它使用显式提供的加载器,并且懒惰地初始化类(在第一次使用时).

请注意,有一个Class.forName()也需要一个ClassLoader.