什么时候加载类?

Tim*_*nko 6 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;
}
Run Code Online (Sandbox Code Playgroud)

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

  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. Test2和是否Test3加载?如果是的话那么?

rge*_*man 5

加载类时,JLS涵盖了第12.4.1节.

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

  • T是一个类,并且创建了T的实例.

  • T是一个类,并且调用由T声明的静态方法.

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

  • 使用由T声明的静态字段,该字段不是常量变量(第4.12.4节).

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

(剪断)

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

第5章讨论加载,链接和初始化类.

The Java Virtual Machine dynamically loads, links and initializes classes and interfaces. Loading is the process of finding the binary representation of a class or interface type with a particular name and creating a class or interface from that binary representation. Linking is the process of taking a class or interface and combining it into the run-time state of the Java Virtual Machine so that it can be executed. Initialization of a class or interface consists of executing the class or interface initialization method (§2.9).

Your questions:

  1. Declaring a variable doesn't load the class. But loading happens before linking, and linking happens before initialization. So, when a class is loaded, it is also then linked and initialized.
  2. Integer在代码运行之前,该类由JVM(以及许多其他语言基础类)加载.
  3. 现在Test加载了类,因为创建了一个新实例.
  4. Test4 没有加载,因为只使用了一个常量变量,这与上面的第4条规则相冲突.
  5. Test3并且Test2在加载后Test加载,因为Test2对象是在Test实例初始化程序中创建的,这也导致Test3(超类)被加载.

使用JVM选项运行代码-verbose:class时会确认这一点.