在讲解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一个对象时,则不会出现这种情况。
在别的包装类中,也有缓存技术。
| 包装类型 | 基本数据类型 | 缓存对象(基本数据类型值) | 
|---|---|---|
| Boolean | boolean | true,false(全部值) | 
| Byte | byte | -128~127(全部值) | 
| Short | short | -128~127 | 
| Character | char | 0~127 | 
| Integer | int | -128~127(默认为127) | 
| Long | long | -128~127 | 
| Float | float | 无缓存值 | 
| Double | double | 无缓存值 | 



















