Class.forName()与ClassLoader.loadClass() – 哪个用于dynamic加载?

dynamic加载类时,何时适合使用

Class.forName("SomeClass"); 

何时使用

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

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

他们是完全不同的!

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

返回与具有给定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应用程序创build一个类加载器(以便稍后可以卸载该Web应用程序并释放内存 – 您需要一个专用的类加载器才能工作!)。 在这种情况下,你可以看到这两个调用将产生完全不同的结果!

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

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

loadClass是一个ClassLoader方法,所以它使用一个明确提供的加载器,并在第一次使用时懒惰地初始化类。

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

他们基本上是做同样的事情。 虽然使用的ClassLoader可能会有所不同。 Class.forName使用您从this.getClass()。getClassLoader()获得的类加载器,而您的其他代码指定使用系统类加载器。

在大多数应用程序中,这将是相同的类加载器,但在更复杂的环境中,例如J2EE应用程序或小应用程序,情况可能并非如此。

ClassLoader是一个抽象类,但是你的应用程序总是被一个类加载器加载,可能会有自定义的类加载器,比如networking类加载器或者任何其他的源代码。

另一方面,Class本身表示类和接口,而Class类有一个forName函数,它使用当前类加载器,默认情况下应用程序正在运行该类加载器以加载类。

这里是Class.forName的源代码,然后调用调用类加载器。

 public static Class<?> forName(String className) throws ClassNotFoundException { return forName0(className, true, ClassLoader.getCallerClassLoader()); } 

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#forName(java.lang.String

提示:Primordial类加载器http://docs.oracle.com/javase/1.4.2/docs/guide/security/spec/security-spec.doc5.html

  • Class.forName()加载并初始化类。 在类加载器子系统中,它执行所有三个阶段,即加载,链接和初始化阶段。

  • ClassLoader.loadClass()行为,这会延迟初始化,直到第一次使用类。 在类加载器子系统中,它只执行两个阶段,即加载和链接阶段。

例如:

 class MyClass { static { System.out.println("static block in MyClass"); } } public class TestCase1 { public static void main(String... args) throws Throwable { Class.forName("A"); } } //The above TestCase1 produce output: static block in MyClass public class TestCase2 { public static void main(String... args) throws Throwable { ClassLoader.getSystemClassLoader().loadClass("MyClass"); } } //The above TestCase2 not produce any output 

我喜欢在Java加载类…

这实际上取决于运行应用程序的上下文。如果从Web上下文使用它,而不是只使用命令行程序,则会得到不同的结果。

我也遇到了问题,取决于你的ClassPath看起来像什么,我期待发生。

这篇 JavaWorld文章解释了很多。