【喜欢的话可以一键三连+关注哦~】 你的三连+关注是对我最大的支持!之后也会继续更新本专栏呦 ~~
连接阶段
验证:
验证内容是否满足《Java虚拟机规范》(这个阶段程序员一般不需要参与)
准备:
给静态变量(static)分配内存并设置初始值
final修饰的基本数据类型的静态变量,准备阶段直接会将代码中的值进行赋值。
解析:
将常量池中的符号引用替换成指向内存的直接引用
符号引用就是在字节码文件中使用编号来访问常量池中的内容
直接引用不在使用编号,而是使用内存中地址进行访问具体的数据
初始化阶段
这个value的值为1是从初始化阶段来完成的。
初始化阶段会执行静态代码块中的代码,并为静态变量赋值。
初始化阶段会执行字节码文件中clinit(类的初始化)部分的字节码指令。
具体流程:
首先执行源码里面的那个语句(如图片),然后执行字节码指令将常量1放入操作数栈。
将操作数栈中的1赋值给常量池中编号为2的变量,它就是Demo1里面的value变量。由于在之前在堆区中给value赋值为0,这时我们需要将操作数栈中的1赋值进去。
之后的步骤就与上面的流程类似(图片在下)
那么问题来了,如果说将上面两句话对调顺序,结果会怎么样呢?
由于clinit方法中的执行顺序与Java中编写的顺序是一致的,所以最终的结果是1
以下几种方式会导致类的初始化:
1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化。
2.调用Class.forName(String className)。
3.new一个该类的对象时。
4.执行Main方法的当前类。
这个参数的开启方式:
最后在点击一下OK,我们就开启成功了!!!!
大厂面试题!!!!!!
执行main方法先初始化Test1的初始化方法,输出结果为DA。
执行两次Test1的构造方法,输出结果为DACBCB
插一嘴:是不是有人会有疑惑?为什么C会在B前面执行?其原因是{}是构造代码块,每一次创建对象时执行,始终在构造方法前执行。
整体的执行步骤:
clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的。
1.无静态代码块且无静态变量赋值语句。
2.有静态变量的声明,但是没有赋值语句。
3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。
出现继承初始化阶段会怎么样呢?
直接访问父类的静态变量,不会触发子类的初始化。
子类的初始化clinit调用之前,会先调用父类的clinit初始化方法。
标签:初始化,变量,静态,clinit,阶段,JVM,执行,赋值 From: https://blog.csdn.net/m0_72647000/article/details/139274894