静态内部类在加载时是否也加载了它所在的外部类
,这是我们讨论的核心
列出网上一些贴子的代码:
public class StaticClass {
public static long OUTER_DATE = System.currentTimeMillis();
static {
System.out.println("外部类静态块加载时间:" + System.currentTimeMillis());
}
public StaticClass() {
System.out.println("外部类构造函数时间:" + System.currentTimeMillis());
}
static class InnerStaticClass {
public static long INNER_STATIC_DATE = System.currentTimeMillis();
static{
System.out.println("静态内部类静态块加载时间:" + System.currentTimeMillis());
}
}
class InnerClass {
public long INNER_DATE = 0;
public InnerClass() {
INNER_DATE = System.currentTimeMillis();
}
}
}
这是我们测试的主要类,我们在两个条件下测试:
- 静态内部类所在的类的
main
方法中 - 重新建一个测试类
1.静态内部类所在的类的main
方法中测试
测试代码:
public static void main(String[] args) {
System.out.println("静态内部类加载时间:"+StaticClass.InnerStaticClass.INNER_STATIC_DATE);
}
测试结果:
外部类静态块加载时间:1587093662805
静态内部类静态块加载时间:1587093662806
静态内部类加载时间:1587093662806
注意这是静态内部类所在的类
2.新建测试类
测试代码:
public class test {
public static void main(String[] args) {
System.out.println("静态内部类加载时间:"+StaticClass.InnerStaticClass.INNER_STATIC_DATE);
}
}
测试结果:
静态内部类静态块加载时间:1587093781882
静态内部类加载时间:1587093781882
3.静态内部类引用了外部类的静态变量
还是在新建的测试类中测试,改变代码中的一部分
static class InnerStaticClass {
public static long id = OUTER_DATE;//引用了外部类的静态属性
public static long INNER_STATIC_DATE = System.currentTimeMillis();
int sum = 20;
static{
System.out.println("静态内部类静态块加载时间:" + System.currentTimeMillis());
}
}
public static void main(String[] args) {
System.out.println(StaticClass.InnerStaticClass.INNER_STATIC_DATE + " " + StaticClass.InnerStaticClass.id);
}
看输出情况
外部类静态块加载时间:1587439343790
静态内部类静态块加载时间:1587439343790
1587439343790
在java虚拟机规范中,只要使用了一个类的静态属性,就必须将这个类初始化
4.外部类创建时不会加载静态内部类
和第三步有点类似,外部类的加载不会加载静态内部类,但当使用了静态内部类的变量就会加载,这里延申一下加载顺序:有父类的情况
- 加载父类
1.1 为静态属性分配存储空间并赋初始值
1.2 执行静态初始化块和静态初始化语句(从上至下) - 加载子类
2.1 为静态属性分配存储空间
2.2 执行静态初始化块和静态初始化语句(从上至下) - 加载父类构造器
3.1 为实例属性分配存数空间并赋初始值
3.2 执行实例初始化块和实例初始化语句
3.3 执行构造器内容 - 加载子类构造器
4.1 为实例属性分配存数空间并赋初始值
4.2 执行实例初始化块和实例初始化语句
4.3 执行构造器内容
5 回到main()
内部类的加载过程也一样
结论:
在没有引用外部类的静态属性或方法的情况下,静态内部类的加载不需要依附外部类,在使用时才加载,加载静态内部类的时候不会加载外部类,现在还不能给出解释原因,大概就是在第一种测试方式中,mian
在外部类,要使用main
就得先加载外部类
,大家先记住这个结论就可以了
参考:详解 Java 内部类