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

时间:2011-11-11 21:45:24

标签: java classloader

动态加载类时,何时使用

Class.forName("SomeClass");

我应该何时使用

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

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

6 个答案:

答案 0 :(得分:145)

他们完全不同!

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

  

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

true这里是指你想要初始化这个类吗?

另一方面,ClassLoader.loadClass(String)

  

调用此方法相当于调用loadClass(name, false)

(这里,boolean与初始化无关;但是如果你检查loadClass(String,boolean)文档,你会看到它所做的只是加载类,而不是初始化它。)

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

  • 使用加载了调用此代码的类的类加载器
  • 初始化类(即,将运行所有静态初始化程序)

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

  • 使用“system”类加载器(which is overridable
  • 没有初始化类(比如,如果你使用它来加载JDBC驱动程序,它将不会被注册,你将无法使用JDBC!)

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

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

答案 1 :(得分:7)

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

loadClassClassLoader方法,因此它使用显式提供的加载器,并且懒惰地初始化类(首次使用时)。

请注意,Class.forName()还需要ClassLoader

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

ClassLoader是一个抽象类,但是您的应用程序总是由类加载器加载,可能有自定义类加载器,如网络类加载器或任何其他源。

另一方面,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

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

答案 4 :(得分:0)

  • 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

答案 5 :(得分:-2)

我喜欢java中的类加载...

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

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

This JavaWorld文章解释了很多相关内容。