深入java虚拟机学习 -- 类的加载机制(续)
2018-03-01 11:59
183 查看
昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解。
这里我先把昨天的两份代码贴过来,重新看下:
第一份代码执行结果:
第二份代码执行结果:
我们知道Java虚拟机为类的静态变量分配内存,并设置默认的初始值实在准备阶段开始的,这里所设置的初始值通常情况下是类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。有很多人还是不太明白默认零值和显示赋值到底是什么意思,下面我们距离来说:
上面的代码在经过了准备阶段后的结果是:
大家可能对b=0没有任何疑问,而a=0;就是上面说的“类型默认的零值”,也就是说准备的阶段等号右边的1并不会赋值给a,不知道这么解释大家能不能明白,而类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量 赋予正确的初始值。
当Singletom类在准备阶段,由于只是分配数据类型默认值,所以此时的counter1=0、counter2=0;
当Singletom类在初始化阶段,1调用了Singleton的实例并对counter1和counter2分别进行了++操作,所以此时的counter1=1,counter2=1,由于2中未对counter1进行显式初始化,所以此时的counter1仍然保留值1,而counter2被显式赋值成0,所以counter2在初始化阶段又被改为0
在经过了准备、初始化阶段后的最终结果就变成了counter1:1、counter2:0
第二份代码是将1->2->3的顺序修改为2->3->1,我们按着上面的思路重新分析发现很清晰的就知道了结果
准备阶段没有任何变化,counter1=0、counter2=0;
初始化阶段,counter1没有被显式赋值,所以counter1仍然保留值0,counter2被显式赋值为0,所以counter2=0,到第三步时调用了Singleton()方法,此时执行了++操作
最终结果 counter1:1、counter2:1
这里我先把昨天的两份代码贴过来,重新看下:
class Singleton { private static Singleton singleton = new Singleton(); //第一份代码的位置 public static int counter1; public static int counter2=0; private static Singleton singleton = new Singleton();//第二份代码的位置 private Singleton(){ counter1++; counter2++; } public static Singleton getInstance(){ return singleton; } } public class Demo { public static void main(String[] args){ Singleton singleton=Singleton.getInstance(); System.out.println("counter1:"+singleton.counter1); System.out.println("counter2:"+singleton.counter2); } }
第一份代码执行结果:
第二份代码执行结果:
类是如何被加载的
让我们再来回顾下上篇文章的加载顺序我们知道Java虚拟机为类的静态变量分配内存,并设置默认的初始值实在准备阶段开始的,这里所设置的初始值通常情况下是类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。有很多人还是不太明白默认零值和显示赋值到底是什么意思,下面我们距离来说:
public class Sample{ private static int a=1; private static int b; }
上面的代码在经过了准备阶段后的结果是:
a=0; b=0;
大家可能对b=0没有任何疑问,而a=0;就是上面说的“类型默认的零值”,也就是说准备的阶段等号右边的1并不会赋值给a,不知道这么解释大家能不能明白,而类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量 赋予正确的初始值。
private static int a=1; 表示a被显式初始化成1;
private static int b; 这里的b并没有被显式初始化,所以此时b的值仍然为0;
案例分析
好了,说了这么多开始分析案例,我们知道类是自上而下执行的,所以第一份代码解析如下当Singletom类在准备阶段,由于只是分配数据类型默认值,所以此时的counter1=0、counter2=0;
当Singletom类在初始化阶段,1调用了Singleton的实例并对counter1和counter2分别进行了++操作,所以此时的counter1=1,counter2=1,由于2中未对counter1进行显式初始化,所以此时的counter1仍然保留值1,而counter2被显式赋值成0,所以counter2在初始化阶段又被改为0
在经过了准备、初始化阶段后的最终结果就变成了counter1:1、counter2:0
第二份代码是将1->2->3的顺序修改为2->3->1,我们按着上面的思路重新分析发现很清晰的就知道了结果
准备阶段没有任何变化,counter1=0、counter2=0;
初始化阶段,counter1没有被显式赋值,所以counter1仍然保留值0,counter2被显式赋值为0,所以counter2=0,到第三步时调用了Singleton()方法,此时执行了++操作
最终结果 counter1:1、counter2:1
相关文章推荐
- 深入java虚拟机学习 -- 类的加载机制(三)
- <<深入Java虚拟机>>-虚拟机类加载机制-学习笔记
- Java程序员从笨鸟到菜鸟之(九十七)深入java虚拟机(六)——类加载的父亲委托机制
- java学习——java基础(十)之类加载机制
- 某驱动的内核调试检测学习内核调试引擎加载机制
- JVM学习笔记一:类加载机制介绍
- 深入Java虚拟机JVM类加载初始化学习笔记
- 深入学习Java虚拟机——类加载机制
- Java虚拟机学习 - 类加载机制
- java类加载器学习2——自定义类加载器和父类委托机制带来的问题/JAVA类加载的委托模型/Java的委托
- android 开发零起步学习笔记(十):UI控件动态加载机制浅析
- Java程序员从笨鸟到菜鸟之(九十七)深入java虚拟机(六)――类加载的父亲委托机制
- Java虚拟机学习 - 类加载机制
- 深入java虚拟机(六)——类加载的父亲委托机制
- JVM学习笔记三:JVM类加载机制
- JVM学习笔记:虚拟机的类加载机制
- 【PHP进阶学习】—类的自动加载机制
- Java学习笔记—JVM的类加载机制
- Java虚拟机学习(四)-类的加载机制
- 转深入Java虚拟机 之四:类加载机制