• 字节码加载和class实例的顺序问题


    刷头条的时候看到了这个:  你做会错的一道Java面试题:字节码加载和class实例的顺序问题

    以前也看到过,应该是阿里的校招笔试题,当时懒得理这种工作中毫无意义的东西。

    今天突然来了兴趣,就想看看能不能靠自己的知识来理清其中的逻辑,结果还不错,(*^_^*)。

    原题略绕,不直观,先来个精简版:

     1 public class A {
     2     static{
     3         System.out.println("我是静态代码块");
     4     }
     5 
     6     {
     7         System.out.println("实例代码块");
     8     }
     9 
    10     public A(){
    11         System.out.println("构造方法");
    12     }
    13 
    14     public static void main(String[] args){
    15         new A(); //放开注释,执行,看一下实例代码块和构造方法的执行顺序
    16     }
    17 }

    上面的代码,直接执行,即可观察到创建实例时的加载执行顺序

    执行结果如下:

    我是静态代码块
    实例代码块
    构造方法

    很明显,一般情况下,创建实例的执行顺序就是:静态代码块 > 实例代码块 > 构造方法。

    不知道你们有没有考虑过,为什么要按照这种顺序来?

    其实很简单,要满足依赖前置条件!  

    第一点:因为静态变量的可以被直接调用,所以静态变量部分必须先加载并创建;

    第二点:因为静态代码块是在所有静态变量加载完毕后一次性执行的,所以其执行要晚于所有静态变量的加载; 

    第三点:实例代码块是在创建实例的时候执行的,确切的说,是在实例的内存空间分配完毕,而在构造进行之前执行的。-- 如果学过C++,你应该知道这个。 

    OK,已经有了上面三点,那我们再来推一下该面试题中的情况。

    还是先用简化版本,方便看懂:

    public class A {
        private static A a = new A(); //静态实例变量
    
        static{
            System.out.println("我是静态代码块");
        }
    
        {
            System.out.println("实例代码块");
        }
    
        public A(){
            System.out.println("构造方法");
        }
    
        //TODO 执行空的main方法,就是只加载字节码。可以有效测试加载过程中的顺序。
        public static void main(String[] args){
            // new A(); //放开注释,执行,看一下实例代码块和构造方法的执行顺序
        }
    }

    相对于前面那一版,这里只增加了一个本类的静态实例变量 a 。当然还注释掉了main方法中的 new A(),因为我们不需要额外的实例创建来干扰观察。

    执行main方法,结果如下:

    实例代码块
    构造方法
    我是静态代码块

    用上面三条依赖前置条件推理一下看看:

    ①先创建静态实例变量,结果执行new A();②而创建实例必然导致实例代码块的先执行,再执行构造代码块!

    ③执行完构造代码块,静态实例变量a就构造完毕,此时所有静态变量构建完毕,于是执行静态代码块!

    原文中有多个静态变量、静态实例变量,静态实例变量的创建还会修改静态变量,让推理每一步静态变量的值。

    其实再加上一条即可推理出来:按照声明顺序加载

    总之,虽然知道了原理,但是很烦这种推理题 - 把人搞得晕晕的。

  • 相关阅读:
    索引的优缺点
    php中创建和调用WebService
    Redis常用数据结构和操作
    PHP的array_merge
    数据库最左前缀原则
    Mysql+Sphinx实现全文搜索
    YAPI安装和使用
    根据导入xlxs的文件,来写入数据库
    操作RDS文档说明
    springboot查找配置文件路径的过程
  • 原文地址:https://www.cnblogs.com/larryzeal/p/8135628.html
Copyright © 2020-2023  润新知