Java类加载过程中的一点小陷阱
2016-10-21 11:21
162 查看
0.问题阐述
最近看到一到面试题,答案让人非议所思。代码
/** * 类的初始化测试 * @author Jason * */ public class Single { private static Single instance = new Single(); public static int count1; public static int count2 = 0; public Single() { count1++; count2++; } public static Single getInstance(){ return instance; } public static void main(String[] args) { System.out.println("count1 = "+Single.count1); System.out.println("count2 = "+Single.count2); } }
结果
count1 = 1
count2 = 0
很奇怪对不对,count1和count2的区别就是count1没有赋初始值,然后结果就不同了。然后把这句代码
private static Single instance = new Single();放到count2声明的后面,就会发现输出的结果是1。结果很匪夷所思,但是其实是类的加载过程导致的必然结果,只要学习一下类的加载过程就可以理解了。下面先介绍一下类的加载过程。
1. 类的加载过程
JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize),其中链接又分为三个步骤。1.加载:查找并加载类的二进制数据
2.链接
① 验证:确保被加载的类的正确性
② 准备:为类的静态变量分配内存,并将其初始化为默认值
③ 解析:把类中的符号引用转换为直接引用
3.初始化:为类的静态变量赋予正确的初始值(这个不是默认值)
每个步骤就不在此详细介绍了,我们需要关注的是链接的第二个步骤准备,还有类加载过程的第三个步骤初始化,这两个步骤看起来很相像,但是是很不同的,默认值是指类的静态变量的数据类型的默认值,如数值型的默认值是0,布尔型的默认值是false,引用型的默认值是null。而初始值是指我们指定赋予给变量的,例如上面的
public static int count2 = 0;中的0就是我们赋予变量的初始值,当然也可以是其它的整型数值。
看完类的加载过程我们还得了解一下Java程序对类的使用方式,因为这
跟类是否会被初始化有关
2. Java程序对类的使用方式
Java程序对类的使用方式可分为2种,主动使用和被动使用,只有当类是主动使用的时候,才会进行类的初始化。2.1 主动使用
1.创建类的实例2.访问某个类或接口的静态变量,或者对该静态变量赋值
3.调用类的静态方法
4.反射(如Class.forName(“edu.jyu.Test”))
5.初始化一个类的子类
6.Java虚拟机启动时被标明为启动类的类(如在命令行中敲java Test)
2.2 被动使用
除了上述六种情况,都是对类的被动使用,都不会导致类的初始化3. 程序分析
好了,现在根据上面的这些知识,我们就可以揭开这个程序的面纱了,下面就详细说一下程序执行的过程。1.从main方法开始,第一句代码是
System.out.println("count1 = "+Single.count1);,这句代码中调用了Single类的静态变量count1,于是满足主动使用的第2条,于是类会被加载并且会被初始化。
2.在Single类被加载的时候,jvm会为类的静态变量分配内存,并且设置默认的初始值,于是变量instance 的值为null,count1和count2的值都为0。链接的准备阶段完毕。
3.因为SIngle类是主动使用,所有会进行类的初始化,即是将“=”右边的值赋给变量。变量instance的值就会等于 new Single()产生的对象的引用,而在new Single()中,又执行了count1++;count2++;所以此时count1和count2的值都变成了1。
4.接下来是为count1和count2赋初始值,因为count1没有指定初始值,所有count1还是等于1,而count2有初始0,所以将0赋给count2,于是最终答案就变为了count1=1,count2=0。
如果上面的内容有错误的地方或者讲的不好的地方,还请大家指点一下,我好及时修改
相关文章推荐
- 实例解析-Java程序的加载过程
- 优化Java applets 加载过程
- java类加载过程
- java程序的加载过程
- java程序的加载过程
- 解析Java Class Loader 类加载过程
- java程序的加载过程
- Java类的加载过程
- java程序在执行过程中,类,对象以及它们成员加载、初始化的顺序如下:
- Java 程序加载过程
- java web.xml被文件加载过程,各节点加载顺序总结
- 通过类字面常量解释接口常量为什么只能定义为static final,类加载过程---Thinking in java
- Java 理论和实践: 了解泛型 识别和避免学习使用泛型过程中的陷阱
- Java--Java程序的加载过程
- 多多吃红薯,好好学java--浅析类加载过程及类加载器(一)
- 实例解析-Java程序的加载过程
- 通过类字面常量解释接口常量为什么只能定义为static final,类加载过程---Thinking in java
- 对于Java类加载过程中的顺序问题探究
- java类加载过程
- java加载class过程