代码评审思考--java的封包解包及Integer内部缓存

java的封包解包及Integer内部缓存

导语:

之前项目组进行了代码评审,大家讨论的时候有位大神抛出了一个观点,在使用比较时不要使用封装类Integer进行比较,容易出问题。因为描述的不是特别清楚,我在家又仔细思考了下。下面是研究成果,与大家分享。

java的自动装箱

我觉得有必要先解释一下这个概念,我将从此引申此文的后续。

简单解释下封包拆包,其实就是java会自动把基本类型封装成对象。我百度了下这个关键字。第一篇文章是这么写的:
919036-20170412000312579-111790665.png
很简单吧,但是我写了个测试类之后发现了个问题。
919036-20170412000522032-723191627.png
请看代码第19到第22行,我们都知道,在java中双等于==是比较对象,equals方法是要看调用的对象是否有重写这个方法,要看实际。
在Integer对象中,equals被这么重写。
919036-20170412000900954-1713605917.png
那么问题来了:
System.out.println(c_1 == f_1);// true 有问题,按照我百度的第一篇文章描述c_1和f_1都是new的一个新Integer对象,此处不应该为true

System.out.println(g_1 == h_1);// false 没问题,==比较对象,虽然值都为1,但都是new出来的Integer,所以对象不同。但如果这样为什么c和f是true???
所以事实到底是怎么样的呢,我对class文件进行了反编译,看到了这样的内容:
919036-20170412001641766-1083052220.png
可以看到,当我编写这样的代码时
Integer c_1 = 1;
java最后实际执行的是:
Integer c_1 = Integer.valueOf(1);
而不是我百度来的:
Integer c_1 = new Integer(1);
在让我们看看valueOf这个方法:
919036-20170412001931532-1343285950.png

顺着找到了一个叫 IntegerCache的内部类:
919036-20170412002026188-729272221.png
结合内部类及Integer的valueOf方法,大家应该明白了点什么了吧。
没错,实际的逻辑是这样的:

内部类的静态代码块初始化了一个长度为high+128长度的Integer数组(可以看到high跟环境有关,默认的话是127),当编写着使用java的自动装箱这一机制的时候,实际调用的是Integer的valueOf方法,方法会判断入参是否在范围内。
如果在范围内,返回其实是一个静态数组里的。也就是说Integer c_1 = 1 与 Integer f_1 = 1 返回的其实是同一个对象,而Integer g_1 = 128;由于超过了范围,是new 的一个新对象。

再回过头来看看百度的第一篇文章,我可以肯定告诉你,这个是不对的。
919036-20170412003115782-605744525.png

我想说的是,百度是个好东西,人家分享知识也是好意。但汲取知识的你更需要抱着怀疑的心态去认真验证每一个说法,别人的写的真的不一定就是对的,包裹我上面写的所有内容。
共勉。

最后最后,其实java中还有很多同样机制的东西。
919036-20170412003507235-994090910.png

转载于:https://www.cnblogs.com/braba/p/6697089.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值