概述:
本文通过引入一道面试题来解析类加载、类链接、类初始化过程,以及创建创建对象、对象初始化和程序执行的过程。
你将收获:
1、精通类加载、类链接、类初始化过程
2、深入源码层面了解类初始化、对象初始化的原理
3、额外的收获。(- 解不出题的人收获)
目录:
1、面试题
2、类加载、类链接、类初始化的知识点
3、深入字节码源码,解析面试题
4、答疑解惑
5、全文知识点总结
话不多说,开干! :说说下面程序的输出是什么?
(答案在文末),如果你有疑问,尝试看看下文。
在解释程序前,我们先铺垫类加载、链接、初始化、创建对象、对象初始化的知识点,简单举例说一下程序是怎么运行起来的,这样更有利于大家解题:
程序执行的流程:
1、输入“java Test”命令
JVM企图运行Test类的main方法,发现Test类没加载到内存中
2、JVM加载、链接、初始化Test类。
这里加载、链接两个概念不明白不要紧,不影响我们解题。但要说说“类初始化”的概念,因为从类初始化这步开始涉及 java代码的执行
初始化概念:初始化是指执行类或接口的初始化方法<clinit>(<java虚拟机规范>的描述)。这里的<clinit>方法,大家是 虚拟机自己生成的一个方法,在初始化阶段被JVM执行,后面会看到。
初始化规则:static变量初始化代码和static代码块中的代码,在类初始化这步按照在代码中书写的顺序被执行。类初始化 前,其直接超类已经被初始化,直接超类的直接超类也需如此(<java虚拟机规范>的描述)。
3、执行Test类的main方法
前面知识的铺垫,还是有点抽象,那么我根据javac编译后的字节码翻译一下代码,这样就会有个具体的直观认识:
答疑解惑:
其实很多人最大的疑问是在“ static Son son = new Son();”这行代码,这里不用纠结,虚拟机规范并没有规定类初始化阶段 不能执行创建对象的逻辑。说白了,类初始化就是JVM执行代码的过程,没什么特别的。
看完上文的解释,大家是不是清楚了这里程序的输出呢!
全文知识点总结:
1、javac编译实现:
javac编译器生成一个<clinit>方法,把“静态变量的初始化语句”和“static代码块语句”按照代码中的顺序编译到<clinit>方法中;
javac编译器把“实例变量的初始化语句”和“实例代码块的语句”按照代码中的顺序编译到了构造方法中;
以上两点从翻译的代码中可以看出来。
2、类初始化:
类初始化前,其直接超类已经被初始化,直接超类的直接超类也需如此。即javac生成的 <clinit>方法由JVM在“类初始化阶段”调用,调用类的<clinit>方法前,必须先调用父类的<clinit>方法。
3、创建对象、对象初始化
执行构造方法在堆中创建一个对象。在没有显示调用父类构造方法情况下,所有构造方法的首行都会隐含调用父类的无参构造方法。
更详细解析参照:http://gitbook.cn/gitchat/activity/5db3f2c857529f30fbf2bac4
程序输出:
4father init block
6Father constructor
1son init block
3son constructor
5Father static block
2Son static block
4father init block
6Father constructor
1son init block
3son constructor
---end---
标签:初始化,超类,代码,创建对象,程序执行,static,JVM,加载 From: https://blog.51cto.com/u_14724733/5978503