Java自动拆装箱与缓存——Java中的128陷阱

在讲解128陷阱之前,需要了解一些概念。

包装器类型

Java是面向对象的语言,但基本类型并不是面向对象的,从而出现了包装器类型,并且包装器添加了更多的属性和方法。如我们在使用集合类型Collection的时候就一定要使用包装类型而非基本类型,它相当于将基本类型"包装起来",使它具有了对象的性质,丰富了基本类型的操作。

包装器类包括Integer、Long、Float、Double、Short、 Byte、Character和Boolean

前6 个类派生于公共的超类Number。

包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,包装器类还是final,因此不能派生它们的子类。

自动装箱器

自动将基本数据类型转换为包装器类型。

通过查看Integer.valueOf()方法源码,可以看到这个方法就是将int基本类型转换为Integer包装类型的方法,这个就是自动装箱的底层原理。

自动体现在,例如下图,创建了一个ArrayList对象, 因为在添加时会将int类型自动转换成Integer类型,arrayList.add(c)实际上是执行了 arrayList.add(Integer.valueOf(c))

自动拆箱器

自动将包装器类型转换为基本数据类型。

拆箱过程是通过调用包装器的 xxxValue方法实现的(xxx代表对应的基本数据类型)

当把一个Integet对象赋给一个int值时,并不会报错,原因就是在复制给int基本类型时,会自动执行拆箱操作,也就是 int d = arrayList.get(0).intValue();

输出结果为2. 

自动拆装箱与缓存

(这里以Integer为例)

看到上面这个代码时,可以先思考一下输出结果到底是什么。

我们可能会认为上面的两个判断的结果都是false。

虽然比较的值是相等的,但是由于比较的是对象,而对象的引用不一样,所以会认为两个是false的。

但其实并不是这样的,输出的结果第一个是true,这就和Integer中的缓存机制有关,也是传说中的128陷阱

在Integer的valueOf()方中,当数值在-128-127之间时,数值都存储在一个cache数组中,该数组相当于一个缓存,当我们在-128-127之间进行自动装箱的时候,我们就直接返回该值在内存当中的地址,所以在-128-127之间的数值用==进行比较是相等的,因为判断的都是同一个对象的地址。而但如果不在这个区间的数,则需要新开辟一个内存空间,比较的就不是同一个对象,所以不相等。

 如果是new一个对象时,则不会出现这种情况。

在别的包装类中,也有缓存技术。

包装类型基本数据类型缓存对象(基本数据类型值)
Booleanbooleantrue,false(全部值)
Bytebyte-128~127(全部值)
Shortshort-128~127
Characterchar0~127
Integerint-128~127(默认为127)
Longlong-128~127
Floatfloat无缓存值
Doubledouble无缓存值

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赚钱去流浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值