博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字节码加载和class实例的顺序问题
阅读量:5082 次
发布时间:2019-06-13

本文共 1517 字,大约阅读时间需要 5 分钟。

刷头条的时候看到了这个:  

 

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

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

 

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

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就构造完毕,此时所有静态变量构建完毕,于是执行静态代码块!

 

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

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

 

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

 

转载于:https://www.cnblogs.com/larryzeal/p/8135628.html

你可能感兴趣的文章
构建之法阅读笔记02
查看>>
添加按钮
查看>>
移动端页面开发适配 rem布局原理
查看>>
Ajax中文乱码问题解决方法(服务器端用servlet)
查看>>
会计电算化常考题目一
查看>>
阿里云服务器CentOS6.9安装Mysql
查看>>
剑指offer系列6:数值的整数次方
查看>>
js 过滤敏感词
查看>>
poj2752 Seek the Name, Seek the Fame
查看>>
软件开发和软件测试,我该如何选择?(蜗牛学院)
查看>>
基本封装方法
查看>>
bcb ole拖拽功能的实现
查看>>
生活大爆炸之何为光速
查看>>
bzoj 2456: mode【瞎搞】
查看>>
[Typescript] Specify Exact Values with TypeScript’s Literal Types
查看>>
[GraphQL] Reuse Query Fields with GraphQL Fragments
查看>>
Illustrated C#学习笔记(一)
查看>>
理解oracle中连接和会话
查看>>
两种最常用的Sticky footer布局方式
查看>>
Scrapy实战篇(三)之爬取豆瓣电影短评
查看>>