什么时候加载类?

时间:2015-10-20 18:58:39

标签: java class loading

好吧,我有这样的代码:

public class Main {
    public static void main(String[] args) {
        Test t; //1
        Integer i = new Integer(1); //2
        t = new Test(); //3
        System.out.println(Test4.a); //4
    }
}

class Test {
    private int a = 10;
    private Test2 t2; //5

    List<Test2> list = new ArrayList<Test2>() {
        {
            for (int i = 0; i < a; i++) {
                add(new Test2()); //6
            }
        }
    };
}

class Test2 extends Test3{
}

class Test3 {
}

class Test4 {
    public static final int a = 4;
}

我不知道(完全或部分)以及何时加载类。所以:

  1. Test t; - 它不是有效用法,但引用t必须是明确的类型。是否加载了测试类(可能是部分,然后是多少个阶段 - 加载\链接\初始化 - 它已经通过)或者没有发生任何事情?
  2. Integer i = new Integer(1); - 在JVM启动时或在此行上加载了Integer?
  3. t = new Test(); - 有效使用。它是从一开始还是从某一点完全加载(见1)
  4. System.out.println(Test4.a); - 是否加载Test4
  5. 是否加载Test2Test3?如果是,那么什么时候?

1 个答案:

答案 0 :(得分:5)

加载类时,JLS, Section 12.4.1

涵盖了
  

类或接口类型T将在第一次出现以下任何一个之前立即初始化:

     
      
  • T是一个类,并创建了一个T实例。

  •   
  • T是一个类,调用T声明的静态方法。

  •   
  • 分配由T声明的静态字段。

  •   
  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)。

  •   
  • T是顶级类(第7.6节),并且执行在词典中嵌套在T(第8.1.3节)内的断言语句(第14.10节)。

  •   

(剪断)

  

在任何其他情况下,不会初始化类或接口。

Chapter 5讨论加载,链接和初始化类。

  

Java虚拟机动态加载,链接和初始化类和接口。加载是查找具有特定名称的类或接口类型的二进制表示并从该二进制表示创建类或接口的过程。链接是获取类或接口并将其组合到Java虚拟机的运行时状态以便可以执行的过程。类或接口的初始化包括执行类或接口初始化方法(第2.9节)。

您的问题:

  1. 声明变量不会加载该类。但加载在链接之前发生,并且链接在初始化之前发生。因此,当一个类被加载时,它也会被链接和初始化。
  2. 在代码运行之前,Integer类由JVM(以及许多其他语言基础类)加载。
  3. 现在加载了Test类,因为创建了一个新实例。
  4. Test4未加载,因为只使用了一个常量变量,这与上面的第4条规则相冲突。
  5. 加载Test3后加载了
  6. Test2Test,因为在Test2的实例初始值设定项中创建了Test个对象,这也导致Test3 1}}(要加载的超类)。
  7. running your code with the JVM option -verbose:class时确认。