点击上方“方志朋”,选择“置顶或者星标”

你的关注意义重大!

有关Java虚拟机类加载机制相关的文章一搜一大把,笔者这里也不必再赘述一遍了。

笔者这里捞出一道code题要各位大佬来把玩把玩,如果你一眼就看出了端倪,那么恭喜你,你可以下山了:

public class StaticTest
{public static void main(String[] args){staticFunction();}static StaticTest st = new StaticTest();static{System.out.println("1");}{System.out.println("2");}StaticTest(){System.out.println("3");System.out.println("a="+a+",b="+b);}public static void staticFunction(){System.out.println("4");}int a=110;static int b =112;
}

问题:请问这段程序的输出是什么?

一般对于这类问题,小伙伴们脑海中肯定浮现出这样的知识点:

Java中赋值顺序:

  1. 父类的静态变量赋值

  2. 自身的静态变量赋值

  3. 父类成员变量赋值和父类块赋值

  4. 父类构造函数赋值

  5. 自身成员变量赋值和自身块赋值

  6. 自身构造函数赋值

按照这个理论输出是什么呢?答案输出:1 4,这样正确嚒?

肯定不正确啦,这里不是说上面的规则不正确,而是说不能简单的套用这个规则。

正确的答案是:

2
3
a=110,b=0
1
4

有没有答对呢?这里主要的点之一:实例初始化不一定要在类初始化结束之后才开始初始化

类的生命周期是:加载->验证->准备->解析->初始化->使用->卸载。

只有在准备阶段和初始化阶段才会涉及类变量的初始化和赋值,因此只针对这两个阶段进行分析;

类的准备阶段需要做是为类变量分配内存并设置默认值,因此类变量st为null、b为0;

需要注意的是如果类变量是final,编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将变量设置为指定的值。

如果这里这么定义:static final int b=112,那么在准备阶段b的值就是112,而不再是0了。

类的初始化阶段需要做的是执行类构造器。

类构造器是编译器收集所有静态语句块和类变量的赋值语句,按语句在源码中的顺序合并生成类构造器,对象的构造方法是(),类的构造方法是(),可以在堆栈信息中看到。

因此,先执行第一条静态变量的赋值语句,即st = new StaticTest (),此时会进行对象的初始化。

对象的初始化是先初始化成员变量,再执行构造方法。因此打印2->设置a为110->执行构造方法(打印3,此时a已经赋值为110,但是b只是设置了默认值0,并未完成赋值动作)。

等对象的初始化完成后,继续执行之前的类构造器的语句。接下来就不详细说了,按照语句在源码中的顺序执行即可。

这里面还牵涉到一个冷知识,就是在嵌套初始化时有一个特别的逻辑。特别是内嵌的这个变量恰好是个静态成员,而且是本类的实例。

这会导致一个有趣的现象:“实例初始化竟然出现在静态初始化之前”。

其实并没有提前,你要知道java记录初始化与否的时机。看一个简化的代码,把关键问题解释清楚:

public class Test {public static void main(String[] args) {func();}static Test st = new Test();static void func(){}
}

根据上面的代码,有以下步骤:

  1. 首先在执行此段代码时,首先由main方法的调用触发静态初始化。

  2. 在初始化Test 类的静态部分时,遇到st这个成员。

  3. 但凑巧这个变量引用的是本类的实例。

  4. 那么问题来了,此时静态初始化过程还没完成就要初始化实例部分了。是这样么?

  5. 从人的角度是的。但从java的角度,一旦开始初始化静态部分,无论是否完成,后续都不会再重新触发静态初始化流程了。

  6. 因此在实例化st变量时,实际上是把实例初始化嵌入到了静态初始化流程中,并且在楼主的问题中,嵌入到了静态初始化的起始位置。这就导致了实例初始化完全至于静态初始化之前。这也是导致a有值b没值的原因。

  7. 最后再考虑到文本顺序,结果就显而易见了。

相信看到这里,心中大概有个结论了吧。

End

文章来源:朱小厮的博客

-更多文章-

如何阅读Java源码?

Java finally语句到底是在return之前还是之后执行?

从 Spring Cloud 看一个微服务框架的「五脏六腑」

Java基础经典面试题汇总

-关注我-

看完了,帮我点个“好看”鸭

点鸭点鸭

↓↓↓↓

哥们,你真以为你会做这道JVM面试题?相关推荐

  1. 刷脸支付代理真有那么好做?小心别中了他们的骗局!

    支付行业的新宠"刷脸支付"有多火?为什么朋友圈那么多人都嚷嚷着要加盟刷脸支付,做刷脸支付代理真有这么简单?光是想想那些在微信群打着"投10万赚70万"的幌子,说 ...

  2. 10道字节跳动C++/Java笔试真题你能做对几道?3道就赢了80%的竞争者(含答案)

    整理了几道字节跳动真题,来试试自己水平有多厉害吧,每题还有答案和详细解答哦. 1.变量a是一个64位有符号的整数,初始值用16进制表示为:0x7FFFFFFFFFFFFFFF.变量b是一个64位有符号 ...

  3. IT运维真需为“邮筒”做提前保护吗?

    话说上海外滩有个邮筒,某天深夜,有个明星闲来无事站在它旁边合了个影.结果,自打照片上了微博之后,邮筒边即排上了此处有史以来最长的人墙.且多以年少靓丽的年轻女孩为主,有的往邮筒里递信,有的摆着相同pos ...

  4. 移动端真机测试怎么做

    准备工作: 1.必须安装了node 环境和npm: 2.手机和电脑在同一个热点或者wifi下: 3.知道你的IP地址: 步骤一. 启动cmd,进入项目根目录,使用指令:npm i -g live-se ...

  5. 赌5毛钱,你解不出这道Google面试题

    作者 | Kevin Ghadyani 译者 | 清儿爸 编辑 | Rachel 出品 | AI科技大本营(ID:rgznai100) 为了更了解其他人对软件工程的看法,我开始疯狂在 YouTube ...

  6. 想去Google做AI?面试题在手,全程无忧!

    作者 | 阿司匹林 出品 | 人工智能头条(公众号ID:AI_Thinker) 凭借强大的技术实力和良好的工作氛围,Google 对求职者一直有着强大吸引力. 虽然 Google 在几年前就已经退出了 ...

  7. 图解|打工人看腾讯这道多线程面试题

    1. 骚动的周五 小黑是大白前同事,现在俩人在不同的公司,但是都做后端开发工作. 虽然两个人都在北京,但是距离不算近,一个在望京,一个在中关村,算是北京几大IT聚集圈之二了. 两个人日常除了工作,业余 ...

  8. 90%的人都不会做的一道笔试题

    关注"Java后端技术全栈" 回复"面试"获取全套大厂面试资料 数组操作的题目,有的确实比较容易,但并非每个问题都是如此.今天就来看道90%的人都不会做的笔试题 ...

  9. 面趣 | 这道微软面试题你会吗?

    参加 2018 AI开发者大会,请点击 ↑↑↑ 问 面试题目: 两个单词如果包含相同的字母,次序不同,则称为字母易位词(anagram).例如,"silent"和"lis ...

最新文章

  1. (转自ITAA)个人问题汇总(workatlab)
  2. Spring的事务属性
  3. c语言矩阵存储,C语言实现特殊矩阵存储
  4. 如何查看Exchange2010中邮箱数据库的用户邮箱占用情况
  5. zabbix查看mysql同步_Zabbix 检测Mysql数据库的主从同步
  6. html5上传使用FileReader,Promise图片预览
  7. java基础学习-(1)面向对象
  8. 将Notepad++配置为Python编译器
  9. C++基础::Stream
  10. c语言 博客园,C语言l|博客园作业10
  11. image转base64
  12. 银联在线 网关支付 (JAVA版)
  13. 中小企业采用云计算的三大障碍
  14. php中怎么添加css样式_html怎么添加css样式?
  15. 什么是和谐操作系统? 华为新操作系统介绍
  16. 读取文件云服务器bcc,读取文件云服务器bcc
  17. Excel无法打开文件xxx.xlsx,因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配...
  18. MacOS 打开软件出现xxx将对您的电脑造成伤害, 您应该将它移到废纸篓. 的解决方式.md
  19. java怎样实现动态数组?
  20. 港科百创 | 未磁科技完成超亿元A轮融资,获国内首张原子磁力计心磁图仪注册证...

热门文章

  1. Spark MLlib之使用Breeze操作矩阵向量
  2. 数论(Lucas定理) HDOJ 4349 Xiao Ming's Hope
  3. SQL性能优化没有那么神秘
  4. japid-controller自动绑定的数据类型
  5. 自定义控件的构建(5)
  6. 我的面试(四)补充1
  7. 【工程基础】校招研发工程师笔试题
  8. 【UVA/Codeforces】1584 Circular Sequence / 792B Counting-out Rhyme(就是一个圈儿...)
  9. 区分 欧几里得距离 曼哈坦距离 明考斯基距离
  10. AI 语言模型真的是越大越好吗?这个模型优于 Gopher