关于静态内部类加载时机的讨论

静态内部类在加载时是否也加载了它所在的外部类,这是我们讨论的核心
列出网上一些贴子的代码:

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 为静态属性分配存储空间并赋初始值
    1.2 执行静态初始化块和静态初始化语句(从上至下)
  2. 加载子类
    2.1 为静态属性分配存储空间
    2.2 执行静态初始化块和静态初始化语句(从上至下)
  3. 加载父类构造器
    3.1 为实例属性分配存数空间并赋初始值
    3.2 执行实例初始化块和实例初始化语句
    3.3 执行构造器内容
  4. 加载子类构造器
    4.1 为实例属性分配存数空间并赋初始值
    4.2 执行实例初始化块和实例初始化语句
    4.3 执行构造器内容
    5 回到main()
    内部类的加载过程也一样

结论:

在没有引用外部类的静态属性或方法的情况下,静态内部类的加载不需要依附外部类,在使用时才加载,加载静态内部类的时候不会加载外部类,现在还不能给出解释原因,大概就是在第一种测试方式中,mian在外部类,要使用main就得先加载外部类,大家先记住这个结论就可以了
参考:详解 Java 内部类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值