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

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

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

和:

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

他们是同义词吗? 在某些情况下,一个比另一个更好? 使用这两种方法做什么和不做什么?

提前致谢。

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,并且布尔参数定义了在加载或不加载类时是否应该初始化。

肖恩的答案是或多或less是正确的,除了几个遗漏/小错误:

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

当通过ClassLoader的类似图结构加载时,情况有影响,也就是说,不是仅仅使用父进行查找。

  • 类的初始化在classLoader w / code的loadClass中执行,如下所示: if (resolve) resolveClass(c); 而ClassLoader实际上可以跳过解决它感觉像,不推荐,但可能的。

使用这两种方法做什么和不做什么?

除非你有很强的想法,为什么你想要ClassLoader.loadClass(String) ,不要直接使用它。 在所有其他情况下,总是依赖于Class.forName(name, true, classLoader)

总的类加载是一个艺术旁边,它不能被覆盖在一个简单的答案(不是在开玩笑艺术部分)

当你使用Class.forName("SomeImpl") ,你通过当前的类加载器(即你正在调用方法的类的加载器)获得类。 它也会初始化这个类。 它与调用Class.forName("SomeImpl", true, currentLoader)的效果相同Class.forName("SomeImpl", true, currentLoader)其中currentLoader将是调用者的类加载器。 在这里看到细节。

第二种方法需要首先select类加载器。 不要像ClassLoader.loadClass("SomeImpl")那样写它,因为它不是一个静态方法。 你需要类似的东西

 final ClassLoader cl = this.getClass().getClassLoader(); Class theClass = cl.loadClass("SomeImpl"); 

注意ClassLoader的子类应该重写findClass方法而不是loadClass 。 这与调用(protected)方法loadClass("SomeImpl", false) ,其中第二个参数指示是否应该完成链接。

有更细微的差别… loadClass方法期望Java语言规范指定的二进制类名称,而forName也可以用于表示原语types或数组类的string。

总体而言,最好使用Class.forName ,如果需要的话指定一个特定的类加载器,以及是否必须初始化,然后让实现找出其余的。 直接使用类加载器很适合在jar或类path中查找资源。

这行不会编译:

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

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

要解决此问题,请按以下三种方式之一创build一个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

loadClass()方法不能被称为static 。 为ClassLoader创build子类,并有一些额外的其他方法来执行操作。 可以通过扩展ClassLoader类来创build自己的类加载ClassLoader 。 在function上,两种方式是相同的。