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上,两种方式是相同的。