包装类高频区间的数据缓存【面试】
基本数据类型的包装类有其高频区域的数据缓存。
其特性:(以Integer为例)
1. Integer的高频区域为:-128~127
2. 在数据位于数据区间-128~127时,会直接复用已有对象(地址相同),在这区间之外的数字才会在堆上产生。即new一个新的对象。
具体看代码:
public class PackingClass {
public static void main(String[] args) {
Integer num1 = 127;
Integer num2 = 127;
System.out.println("值num1==num2=>"+(num1==num2));//结果:true
Integer num3 = 128;
Integer num4 = 128;
System.out.println("值num3==num4=>"+(num3==num4));//结果:false
}
}
从上面的代码可以看出,Integer为127时复用了已有的num1对象,所以使用==判别结果是true。而当值为128时候,由于超出了Integer的高频区域的数据缓存,所以会重新在堆上生成新的对象。
原因:(看Integer的源码)
/*
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
由此可见:高频区域的数值会直接使用已有对象,非高频区域的数值会重新new一个新的对象 。
各包装类高频区域的取值范围:
包装类 | 缓存区 |
---|---|
Boolean | 使用静态final定义,就会返回静态值 |
Byte | -128~127 |
Short | -128~127 |
Character | 0~127 |
Long | -128~127 |
Integer | -128~127 |
注意:Float和Double不会有缓存,其他包装类都有。
而Integer是唯一一个可以修改缓存范围的包装类。
推荐所有的包装类对象之间值的比较都是以equals()方法,因为包装类的非高频区域数据会在堆上产生,而高频区又会复用已有对象,这样会导致同样的代码,因为取值的不同,而产生两种截然不同的结果。
例题:
//int和Integer比较
int i = 100;
Integer j = 100;
System.out.println(i==j);//true
System.out.println(j.equals(i));//true
有人会认为这和Integer的高速缓存有关,但是当值改成128时,结果依然是true,true。
这是因为Integer和int比较时,会自动拆箱为int,相当于两个int比较,值一定是true,true。