假设我有以下课程:
class Caller {
public void createSomething() {
new Something();
}
}
执行此行:
static void main() {
Class<?> clazz = Caller.class;
}
导致JVM加载类Something
还是延迟类加载,直到调用方法createSomething()
为止?
答案 0 :(得分:23)
只有在需要有关该类的信息时才会加载类。
public class SomethingCaller {
public static Something something = null; // (1) does not cause class loading
public static Class<?> somethingClass = Something.class; // (2) causes class loading
public void doSomething() {
new Something(); // (3) causes class loading
}
}
第(2)行&amp; (3)会导致类被加载。 Something.class对象包含只能来自类定义的信息(第(2)行),因此您需要加载该类。对构造函数(3)的调用显然需要类定义。类似于课堂上的任何其他方法。
但是,第(1)行不会导致加载类,因为您实际上并不需要任何信息,它只是对对象的引用。
编辑:在你改变的问题中,你问是否引用Something.class加载该类。是的,它确实。在执行main()之前,它不会加载类。使用以下代码:
public class SomethingTest {
public static void main(String[] args) {
new SomethingCaller();
}
}
public class SomethingCaller {
public void doSomething() {
Class<?> somethingClass = Something.class;
}
}
public class Something {}
此代码不会导致加载Something.class。但是,如果我调用doSomething(),则会加载该类。要对此进行测试,请创建上述类,编译它们并删除Something.class文件。上面的代码不会因ClassNotFoundException而崩溃。
答案 1 :(得分:2)
是的,这将导致在加载包含File.class
引用的类时加载类。不这样做的唯一方法是通过反射引用一个类。然后你可以控制它何时加载。
答案 2 :(得分:-1)
如果您有严格的性能要求,则应考虑编写自定义的ClassLoader对象。这将允许您在不再需要时从内存中转储类。
您需要查看loadClass
类中的findClass
,defineClass
和ClassLoader
方法,覆盖加载并在实现中查找和使用defineClass 。关于编写自定义类加载器的谷歌搜索会显示大量示例代码来执行此操作,但基本上您要将类结果缓存在Map(类名称为Class)中,然后提供一些回调机制以从缓存中删除加载的类当他们不需要时。