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

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

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

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

 public class A {
static{
System.out.println("我是静态代码块");
} {
System.out.println("实例代码块");
} public A(){
System.out.println("构造方法");
} public static void main(String[] args){
new A(); //放开注释,执行,看一下实例代码块和构造方法的执行顺序
}
}

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

执行结果如下:

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

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

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

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

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

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

第三点:实例代码块是在创建实例的时候执行的,确切的说,是在实例的内存空间分配完毕,而在构造进行之前执行的。-- 如果学过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就构造完毕,此时所有静态变量构建完毕,于是执行静态代码块!

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

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

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

字节码加载和class实例的顺序问题的更多相关文章

  1. 模拟jQuery中的ready方法及实现按需加载css,js实例代码

    这篇文章介绍了模拟jQuery中的ready方法及实现按需加载css,js实例代码,有需要的朋友可以参考一下     一.ready函数的实现经常用jQuery类库或其他类库中的ready方法,有时候 ...

  2. Spring源码加载过程图解(一)

    最近看了一下Spring源码加载的简装版本,为了更好的理解,所以在绘图的基础上,进行了一些总结.(图画是为了理解和便于记忆Spring架构) Spring的核心是IOC(控制反转)和AOP(面向切面编 ...

  3. js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面

    js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了, ...

  4. 浏览器加载和渲染html的顺序

    前阵子,在组内给大家做了一次关于“浏览器加载和渲染HTML的顺序”的分享,这里再总结一下吧. AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载! 1.浏览器加载和渲染html的顺序 浏 ...

  5. Struts2配置拦截器,struts2加载常量时的搜索顺序

    1:struts2加载常量时的搜索顺序 1.Struts-default.xml 2.Struts-plugin.xml 3.Struts.xml 4.Struts-properties(自己创建的) ...

  6. 浏览器加载和渲染html的顺序-css渲染效率的探究

    1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...

  7. 浏览器加载和渲染html的顺序(html/css/js)

    最近在学习前端的技术,把html.js.css的基础知识看了看.感觉越看越觉得前端并不比后端容易,技术含量还是相当大的.今天突然想弄明白浏览器到底是怎么加载和渲染html的?html中的DOM.js文 ...

  8. Javascript中页面加载完成后优先执行顺序

    Javascript中页面加载完成后优先执行顺序 document优先于windowwindow优先于element //document加载完成执行方法体 document.addEventList ...

  9. 浏览器加载和渲染html的顺序-css渲染效率的探究(转载)

    1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...

随机推荐

  1. Socket网络编程--Libev库学习(2)

    这一小节讲各个观察器(Watcher) 在libev下面watcher相当于EventHandler这么一个概念,通常里面会绑定fd回调函数以及我们需要关注的事件. 然后一旦触发事件之后会触发我们使用 ...

  2. 菜鸟学EJB(一)——第一个实例

    EJB用了那么长时间了,从来没写过关于它的东西,挺对不住它的.今天先写一个简单的小实例,虽然小但是却能体现出EJB的核心——分布式.我们可以将业务逻辑的接口跟实现部署到一台机器上,将调用它们的客户端部 ...

  3. [Windows Azure] Create a Virtual Network in Windows Azure

    Create a Virtual Network in Windows Azure This tutorial walks you through the steps to create a basi ...

  4. UNIX环境高级编程 apue.h头文件的配置

    http://jimslinbing.blog.163.com/blog/static/85054319201292712414518/ 1.到http://www.apuebook.com下载源码2 ...

  5. 使用jquery提交FormData数据

    https://blog.csdn.net/u011500781/article/details/54931716 http://yunzhu.iteye.com/blog/2177923 ***** ...

  6. CentOS 6.5 yum安装mysql5.6或其他版本【默认yum只能安装mysql 5.1】 by jason

    by jason [备份配置文件] CentOS 6.5 默认yum只能安装mysql 5.1 安装前要检查机器原来是否安装过mysql,如有安装需要先进行数据备份.清理. [root@snails ...

  7. Codeforces Round #215 (Div. 2) D. Sereja ans Anagrams

    http://codeforces.com/contest/368/problem/D 题意:有a.b两个数组,a数组有n个数,b数组有m个数,现在给出一个p,要你找出所有的位置q,使得位置q  q+ ...

  8. eclipse中git插件使用

    1,首先看下文件的几个工作区:Unstaged Changes(本地工作空间),Staged Changes(Add to Index操作之后代码存放的地方),Local Repository(本地仓 ...

  9. 6. 集成学习(Ensemble Learning)算法比较

    1. 集成学习(Ensemble Learning)原理 2. 集成学习(Ensemble Learning)Bagging 3. 集成学习(Ensemble Learning)随机森林(Random ...

  10. git学习(五):git diff魔法

    不同参数下git diff输出并不相同,理解了工作区,暂存区和版本库的关系之后就很容易理解diff了. 工作区.暂存区和版本库的目录树浏览 清除工作区中未被git管理的文件 git clean -fd ...