Java类加载过程中的一点小陷阱

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。


如果上面的内容有错误的地方或者讲的不好的地方,还请大家指点一下,我好及时修改

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值