一、了解128陷阱
想要了解128陷阱,首先要了解包装器类的知识。
1.包装器类
Java中的八种基本类型本身只能标志一种数值,
为了能将基本类型视为对象来处理,并能连接相关的方法
Java为每个基本类型提供了包装器类
①八种基本类型对应的包装器类:
byte—Byte
short—Short
int — Integer
char—Character
long—Long
float—Float
double—Double
boolean—Boolean
②创建包装器类型对象的两种方式:
- 构造方法 new
- Integer i = new Interger(1);
- 调用包装器类型的valueOf方法
- Double d = Double.valueOf(3.14);
③包装器类共同特点:
对象一旦赋值,其值不能再改变
④装箱、拆箱:
- Java中一些运算或程序是有限制的:
- ++/–操作只能对基本数据类型
- 集合中只能存放包装器类型对象
- 装箱: 将基本类型转化为包装器类型 包装器类.valueOf(基本数据类型变量或常量);
- Integer i = Integer.valueOf(10);//10是基本数据类型,i是包装器类型
- 拆箱:将包装器类型转化为基本数据类型XX.XXXvalue();
- int n = i.intValue();//i是包装器类型,n是包装器类型
2、什么是128陷阱
128陷阱指的是两个Integer对象直接用==判定在某个范围内返回为true
两个Integer对象直接用==判定 在某个范围内(-128~127)返回为true;
引用类型用==判定 就是判定的两个对象是不是地址一样
如果传入value数值在-127~128范围内,那么所有在这个范围内被创建的对象实际 都指向同一个地址,即被预创建Integer对象所在的地址
两个Integer对象直接用==判定 在范围外返回为false;
如果传入value数值不在范围内,那么每次被创建的对象都指向一个新的且不同的地址,即通过new关键字由JVM分配的新地址。
一个int和一个Integer对象用==判定返回true
Integer是int的封装类,当int和Integer进行==比较的时候,Integer会自动拆装为int类型,所以返回true
看下面一段代码
public static void main(String[] args) {
int n = 128;
int n1 = 128;
int c = 127;
Integer c1 = 127;
Integer d = 128;
Integer d1 = 128;
System.out.println(n==n1);
System.out.println(c==c1);
System.out.println(d==d1);
Integer.valueOf(13);
}
运行结果是
true
true
false
在上面的示例中我们用Integer定义的数其实是简写形式,完整的写法:(自动装箱)
Integer d = Integer.valueOf(128);
当Ingeter与int比较时为true,因为拆箱总比装箱性能好(装箱要构建新的对象浪费空间)integer默认做了自动拆箱的处理
Integer就是int的包装类,自动装箱就是将基本数据类型转换为包装类;自动拆箱就是将包装类转换成基本数据类型
二、分析128陷阱
我们从源码角度分析
128陷阱出现的原因就是Integer的valueOf方法中有一个存储[-128-127]的catch数组,这个数组就相当于一个缓存,当我们定义的数在-128-127之间时,就直接返回该内存中的地址
在自动装箱的方法中,由源码可知先判断了i是否存在于IntegerCache中的cache数组中,如若存在则直接返回数组中的值,若不存在则构建一个新的Integer对象
规定了cache数组的范围
所以当我们用==比较两个用Integer定义值为128的数时,会返回false,此时n1和n2是封装在两个对象中,比较应用.equals()方法
Integer n1 = 128;
Integer n2 = 128;
System.out.println(n1.equals(n2));
返回true
这就是我们所说的128陷阱