最近遇到一些让我思考的代码。有什么区别:
Class theClass = Class.forName("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();
和
Class theClass = ClassLoader.loadClass("SomeImpl");
SomeImpl impl = (SomeImpl)theClass.newInstance();
他们是同义词吗?在某些情况下,是否优先于另一方?使用这两种方法有什么用,有什么用呢?
提前致谢。
答案 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进行查找。
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
类来创建自己的类加载器。在功能上两种方式都是一样的。