类加载器创建的实例与新关键​​字之间的功能差异

时间:2014-04-24 06:48:36

标签: java

我在课程加载和初始化概念方面有点困惑

1: Class.forName("test.Employee").newInstance();
2: ClassLoader.getSystemClassLoader().loadClass("test.Employee").newInstance();
3: new test.Employee(); 

上面编写的代码的每一行都是创建Employee类的实例,但我不明白这三种方法的区别是什么。

3 个答案:

答案 0 :(得分:2)

除非将类加载到内存中,否则无法创建Object的实例。在所有三种情况下,都会加载类,然后创建实例。

  1. 类由Class.forName("test.Employee")
  2. 加载
  3. 类由ClassLoader.getSystemClassLoader().loadClass("test.Employee")
  4. 加载
  5. 类自动加载,因为第一次引用了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/