Java:Class.forName和ClassLoader.loadClass之间的区别

时间:2011-12-01 16:57:30

标签: java classloader

最近遇到一些让我思考的代码。有什么区别:

Class theClass = Class.forName("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();

Class theClass = ClassLoader.loadClass("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();

他们是同义词吗?在某些情况下,是否优先于另一方?使用这两种方法有什么用,有什么用呢?

提前致谢。

5 个答案:

答案 0 :(得分:18)

Class.forName()将始终使用调用者的ClassLoader,而ClassLoader.loadClass()可以指定不同的ClassLoader。我相信Class.forName也会初始化加载的类,而ClassLoader.loadClass()方法不会立即执行此操作(直到第一次使用它才会初始化)。

在查看初始化行为的摘要时发现了这篇文章。看起来这有你要查找的大部分信息:

http://www.javaworld.com/javaworld/javaqa/2003-03/01-qa-0314-forname.html

这个用法非常酷,不过我之前从未使用过它:

Class.forName(String, boolean, ClassLoader)

它允许您指定ClassLoader,boolean参数定义是否应该在加载类时对其进行初始化。

答案 1 :(得分:11)

Shaun的答案或多或少是正确的,只有少数遗漏/小错误:

  • Class.forName将类与ClassLoader相关联(无论其他父项是否为实际加载它),因此ClassLoader.findLoadedClass下次成功。这是一个非常非常重要的观点,大多数ClassLoader会尝试Class c = findLoadedClass(name); if (c!=null) return c;作为绕过整个查找/查找部分的第一个语句。直接调用ClassLoader.load不会将类添加到已加载的类中。

这种情况在通过类似于ClassLoader的图形结构加载时会产生影响,即不首先使用parent进行查找。

  • 类的初始化是在ClassLoader的loadClass中执行的,代码类似于:if (resolve) resolveClass(c);,ClassLoader实际上可以跳过解决它感觉,不推荐但可能。

使用这两种方法有什么用,有什么用呢?

除非您非常强烈地了解为什么要ClassLoader.loadClass(String),否则请勿直接使用它。在所有其他情况下,始终依赖Class.forName(name, true, classLoader)

整体课程加载是艺术的一部分,它不能用一个简单的答案来涵盖(不是开玩笑的艺术部分)

答案 2 :(得分:3)

使用时使用Class.forName("SomeImpl"),您将通过当前的类加载器(即您正在调用方法的类的加载器)获取该类。它也将initialize课程。它实际上与调用Class.forName("SomeImpl", true, currentLoader)相同,其中currentLoader将是调用者的类加载器。查看详细信息here

第二种方法需要首先选择类加载器。不要像ClassLoader.loadClass("SomeImpl")那样写它,因为它是不是静态方法。你需要像

这样的东西
final ClassLoader cl = this.getClass().getClassLoader();
Class theClass = cl.loadClass("SomeImpl");

请注意,ClassLoader的子类应覆盖findClass方法而不是loadClass。这与调用(protected)方法loadClass("SomeImpl", false)相同,其中第二个参数指示是否应该进行链接。

存在更细微的差异...... loadClass方法需要Java语言规范指定的二进制类名,而forName也可以与表示基本类型或数组类的字符串一起使用。

总之,最好使用Class.forName,如果需要指定一个特定的类加载器以及它是否必须初始化,那么让实现弄清楚其余部分。直接使用类加载器有助于在jar或类路径中查找资源。

答案 3 :(得分:1)

这一行不会编译:

Class theClass = ClassLoader.loadClass("SomeImpl");

因为loadClass不是ClassLoader的静态方法。

要解决此问题,请使用以下三种方法之一创建ClassLoader对象:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
ClassLoader classLoader = Main.class.getClassLoader();      // Assuming in class Main
ClassLoader classLoader = getClass().getClassLoader();      // works in any class

然后致电:

Class theClass = classLoader.loadClass("SomeImpl");

-dbednar

答案 4 :(得分:0)

无法将loadClass()方法称为static方法。为ClassLoader创建子类,并有一些其他方法来执行操作。可以通过扩展ClassLoader类来创建自己的类加载器。在功能上两种方式都是一样的。