我在课程加载和初始化概念方面有点困惑
1: Class.forName("test.Employee").newInstance();
2: ClassLoader.getSystemClassLoader().loadClass("test.Employee").newInstance();
3: new test.Employee();
上面编写的代码的每一行都是创建Employee
类的实例,但我不明白这三种方法的区别是什么。
答案 0 :(得分:2)
除非将类加载到内存中,否则无法创建Object的实例。在所有三种情况下,都会加载类,然后创建实例。
Class.forName("test.Employee")
ClassLoader.getSystemClassLoader().loadClass("test.Employee")
答案 1 :(得分:2)
这三种方法之间的核心差异归结为类在运行时的位置以及您可以使用它们做什么。
例如......
Class.forName("test.Employee").newInstance();
将使用当前班级的ClassLoader
来搜索Employee
包中名为test
的班级。这将允许您发现在编译时可能不可用的类以及动态加载到同一类加载器上下文中的类。如果在当前上下文中找不到类,这也将搜索它的父类加载器...
ClassLoader.getSystemClassLoader().loadClass("test.Employee").newInstance();
这将使用“system”ClassLoader
,这通常是启动主应用程序的那个。
使用这两种方法中的任何一种都是生成动态应用程序的好方法,其中Class
的实际实现在编译类型中是未知的。这里的问题是它会影响可见性并限制你可以用加载的类做什么。
例如,虽然您可能已经加载了test.Employee
类并创建了它的实例,但除非您在编译时引用test.Employee
,否则您希望能够转换它。这通常是interface
非常方便的地方。
同样,您可以在运行时创建自己的ClassLoader
实例并加载类或jar,以提供在编译时实现未知的插件,工厂或管理器。通常,通过使用interface
s。
示例包括java.awt.Toolkit
和JDBC java.sql.Driver
在一天结束时,ClassLoader
机制提供了一种方法,通过该方法可以加载类文件并将其实例化到当前JVM中。 new
关键字执行类似的工作,但结果是在编译时预先确定的
ClassLoader
是一个非常强大的功能,提供了很多功能,但也可能是混乱,特别是它们链接在一起的方式
你可能会发现......
一些帮助
答案 2 :(得分:0)
只是用一个例子来说明并完成其他答案:
public class ClassLoaderTest {
public ClassLoaderTest() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
System.out.println("Current CL: "+getClass().getClassLoader());
System.out.println("Parent CL: "+getClass().getClassLoader().getParent());
// ClassTest class is defined in the current CL so I can dynamically create an instance
// from the current CL and assign it (forName uses the current CL)
ClassTest c1 = (ClassTest)Class.forName("ClassTest").newInstance();
System.out.println("CL using forName: "+c1.getClass().getClassLoader());
// the new keyword creates an instance using the current CL but doesn't have the
// advantages of creating instances dynamically
ClassTest c2 = (ClassTest) new ClassTest();
System.out.println("CL using new: "+c2.getClass().getClassLoader());
// Here we are indicating to use the system CL that in this case is the parent of the current CL
Object c3 = ClassLoader.getSystemClassLoader().loadClass("ClassTest").newInstance();
System.out.println("CL using system CL: "+c3.getClass().getClassLoader());
// This won't work because the ClassTest is defined in the current CL but I'm trying to assign it to a
// dynamically created instance of ClassTest associated to the system CL so:
// java.lang.ClassCastException: ClassTest cannot be cast to ClassTest
// ClassTest c4 = (ClassTest)ClassLoader.getSystemClassLoader().loadClass("ClassTest").newInstance();
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
CustomClassLoader cl = new CustomClassLoader(Test.class.getClassLoader());
cl.loadClass("ClassLoaderTest").newInstance();
}
}
我的输出是:
Current CL: CustomClassLoader@1cfb549
Parent CL: sun.misc.Launcher$AppClassLoader@8ed465
CL using forName: CustomClassLoader@1cfb549
CL using new: CustomClassLoader@1cfb549
CL using system CL: sun.misc.Launcher$AppClassLoader@8ed465
我正在使用此自定义ClassLoader(CL):www.javablogging.com/java-classloader-2-write-your-own-classloader/