参考文章:【https://www.cnblogs.com/maohuidong/p/7843807.html】
前言:
在看单例模式的时候,在网上找帖子看见其中有一种(IoDH) 实现单例的方式,其中用到了静态内部类,文章中有写到当jvm加载外部类的时候,并没有加载静态内部内这和之前自己想的不一样,特意在网上找了一些帖子总结一下。
一、学习前千的疑问:
稍微了解Java虚拟机内的加载过程的步骤,都很清楚,一个类的静态资源、一些常量都是在类加载的时候就被加载金内存中分配空间了,所以我一开始理所当然的以为静态内部类中的静态变量同样属于静态资源,也应该在在内加载的时候被加载,然而实际情况却不是这样的,带着这个问题我上网找了几篇博客查找原因。
二、探究的过程:
在这里我们直接上一段代码,在这里我们分别进行三次测试来:
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();
}
}
}
1、当外部内静态变量被调用
public static void main(String[] args) {
StaticClass outer = new StaticClass();
System.out.println("外部类静态变量加载时间:" + outer.OUTER_DATE);
}
打印结果:
外部类静态块加载时间:1556088212487
外部类构造函数时间:1556088212487
外部类静态变量加载时间:1556088212487
从控制台打印的结果我们可以看到:
外部静态变量调用时,外部内进行了加载(注:静态代码块在类被加载时执行)并且执行了初始化操作(注:构造方法被调用),而静态内部类并没有被加载(注:静态内部类中的静态代码块没有执行),且类的加载顺序必定会在初始化的前面,所有看到先执行了静态代码块中的代码,其次执行了构造方法中的代码,完成上面两部后最后才打印出了静态变量
2、非静态内部类变量调用时:
public static void main(String[] args) {
StaticClass outer = new StaticClass();
System.out.println("非静态内部类加载时间"+outer.new InnerClass().INNER_DATE);
}
打印结果:
外部类静态块加载时间:1556088682706
外部类构造函数时间:1556088682706
非静态内部类加载时间1556088682707
从控制台打印的结果我们可以看到:
非静态内部类变量被调用时的执行结果和外部静态变量被调用的结果一样,并且静态内部类也没有被加载,出现这种情况也在预料之中,因为非静态内部类的初始化不许依赖于外部类,如果想实例化一个非静态内部类,则必须先实例化外部类,所以我们就看到了上面的结果
3、静态内部类中的变量被调用时:
public static void main(String[] args) {
System.out.println("静态内部类加载时间:"+InnerStaticClass.INNER_STATIC_DATE);
}
测试结果:
外部类静态块加载时间:1556089480349
静态内部类静态块加载时间:1556089480352
静态内部类加载时间:1556089480352
从控制台打印的结果我们可以看到:
静态内部类的变量被调用时,我们可以看出外部类进行了加载(注:外部类中的静态代码块中的代码执行了),但是并没有被初始化(注:外部类的构造方法并没有执行),且静态内部类也完成了加载
三、得出结论:
有上面我们进行的测试可以得出结论,静态内部类和非静态内部类一样,都不会因为外部内的加载而加载,同时静态内部类的加载不需要依附外部类,在使用时才加载,不过在加载静态内部类的过程中也会加载外部类