Java包装类Integer-----那些年我们一起踩过的坑

:对于java的数据类型中除了8个基本数据类型外其他都是引用数据类型。但8个基本数据类型都有对应的包装类:byte(Byte),short(Short), int(Integer), long(Long), float(Float),double(Double), char(Character),boolean(Boolean)。
包装类的实质就是将基本数据类型封装成引用数据类型(一个类),也就是我们所说的包装类。下面以Integer为例。

jdk1.5 之前:

构建成一个Integer类型的包装类需要手动调用其构造方法:
eg: Integer i1 = new Integer(123); eg: Integer i2 = new Integer(“123”); 这个过程也叫做装箱。
将包装类还原成一个基本数据类型也需要调用其方法:
eg: int i2 = i1.intValue(); 这个过程也叫做拆箱。

jdk1.5 之后:

出现了自动拆装箱,用起来也方便且灵活。
eg:Integer i2 = 10; 这个过程其实内部自动构建成了一个Integer类型,即自动装箱的过程。
eg:int val = new Integer(10); 这个过程其实内部其实自动还原了一个int类型,即自动拆箱的过程。

但伴随的着应用的灵活和方便,砸们往往在很多细节方面容易忽视,这也就是我们踩坑的原因。

如下:

Integer i1 = 10;
Integer i2 = 10;
Integer i3 = new Integer(10);
Integer i4 = new Integer(10);

判断输出结果:

System.out,println( i1 == i2); // true
System.out,println( i1 == i3); // false
System.out,println( i3 == i4); // false
System.out,println( i1.equals(i2) ); // true
System.out,println( i1.equals(i3) ); // true
System.out,println( i3.equals(i4) ); // true

结果似乎有点出人意料对吧,可能会怀疑自己了判断能力。自信点,把"怀疑"去掉。(手动滑稽) hia~hia

1. 对于 == 比较运算符来说:可以比较基本数据类型也可以比较引用数据类型,基本数据数据类型比较的是值,而引用数据类型比较的是变量中存的内存地址,这点非常清楚不过了。

对于 Integer i1 = 10;Integer i2 = 10; 其实内部都是指向Integer内部一个类加载的时候静态区的一个值为10的Integer包装类对象。
对于 Integer i3 = new Integer(10); Integer i4 = new Integer(10); 实际上在堆内存中分别创建了一个Integer类型的对象,并且分别指向它们。
如下图所示:Java包装类Integer-----那些年我们一起踩过的坑
前3个比较的是引用地址,i1i2** 指向同一引用,i1i3 指向不同引用 ,i3i4指向不同引用。显然可以看出结果。

2. 对于 equals() 方法来说:默认继承至Object,**Java包装类Integer-----那些年我们一起踩过的坑

可以看出,比较的是引用。
但是Integer重写了此方法,

Java包装类Integer-----那些年我们一起踩过的坑
可以看出,比较的是内部的属性值。噢,所以:i1.equals(i2) ; i1.equals(i3); i3.equals(i4) ;比较都是值,结果显然都为true。

你以为这就Vans了嘛?往下看:

我们稍微修改一下:

Integer i1 = 1000;
Integer i2 = 1000;
Integer i3 = new Integer(1000);
Integer i4 = new Integer(1000);

判断输出结果:

System.out,println( i1 == i2); // true // false
System.out,println( i1 == i3); // false
System.out,println( i3 == i4); // false
System.out,println( i1.equals(i2) ); // true
System.out,println( i1.equals(i3) ); // true
System.out,println( i3.equals(i4) ); // true

WTF? 第一个比较怎么回事?false? Are you kidding me?
翻看源码,才知道这玩意有点磨人呀。
Java包装类Integer-----那些年我们一起踩过的坑
1. 可以发现Integer存在一个静态内部类(IntegerCache)作为缓存,里面有256个现有的静态对象存在一个数组(Integer[] cache)中,值得范围是-128 ~ 127;当需要包装成Integer时,包装的数值在这个范围则直接用静态缓存中的,引用直接指向它。
2. 当不在这个范围则会在堆内存中创建一个新的对象。
在此处的 Integer i1 = 1000; Integer i2 = 1000; 会在堆内存中创建两个不同的Integer对象。
Java包装类Integer-----那些年我们一起踩过的坑
所以结果为false。

有没有? 有没有? 复行数十步,豁然开朗的感觉呢Java包装类Integer-----那些年我们一起踩过的坑