先说结论:
- 外部类初次加载,会初始化静态变量、静态代码块、静态方法,但不会加载内部类和静态内部类。
- 实例化外部类,调用外部类的静态方法、静态变量,则外部类必须先进行加载,但只加载一次。
- 直接调用静态内部类时,外部类不会加载。
再看代码:
外部类及内部类:
public class Student {
public static long OUTER_DATE = System.currentTimeMillis();
static{
System.out.println("外部类静态块加载时间:"+System.currentTimeMillis());
}
public Student(){
System.out.println("外部类构造时间:"+System.currentTimeMillis());
}
static class InnerStaticClass {
public static long INNER_STATIC_DATE = System.currentTimeMillis();
}
class InnerClass {
public long INNER_DATE = 0;
public InnerClass() {
INNER_DATE = System.currentTimeMillis();
}
}
public static void timeElapsed() {
for (int i = 0; i < 10000000; i++) {
int a = new Random(100).nextInt(), b = new Random(100).nextInt();
a = a + b;
}
}
public static void outerStaticMethod() {
System.out.println("外部类静态方法执行了");
}
}
测试类:
public class Test {
public static void main(String[] args) {
timeElapsed();
System.out.println("打印时间:" + System.currentTimeMillis() + ".....静态内部类加载时间:" + Student.InnerStaticClass.INNER_STATIC_DATE);
timeElapsed();
System.out.println("打印时间:" + System.currentTimeMillis() + ".....外部类静态变量加载时间:" + Student.OUTER_DATE);
timeElapsed();
System.out.println("打印时间:" + System.currentTimeMillis() + ".....调用外部静态方法:" ) ;Student.outerStaticMethod();
timeElapsed();
Student student1 = new Student();
System.out.println("打印时间:" + System.currentTimeMillis() + ".....非静态内部类加载时间:" + student1.new InnerClass().INNER_DATE);
}
private static void timeElapsed() {
for (int i = 0; i < 10000000; i++) {
int a = new Random(100).nextInt(), b = new Random(100).nextInt();
a = a + b;
}
}
}
结果输出:
打印时间:1535701354832.....静态内部类加载时间:1535701354832
外部类静态块加载时间:1535701355174
打印时间:1535701355173.....外部类静态变量加载时间:1535701355174
打印时间:1535701355482.....调用外部静态方法:
外部类静态方法执行了
外部类构造时间:1535701355784
打印时间:1535701355784.....非静态内部类加载时间:1535701355785
可以看到,调用静态内部类的变量时,外部类并没有加载。时间与外部类是否加载以及加载时间无关。
而在调用外部类静态变量时,外部类静态块加载了,并且和静态变量一起,随着外部类的加载而初始化了。
至于访问非静态类的变量,首先要获得外部类的一个实例,所以这时候外部类才加载构造函数,故最晚。