什么是128陷阱?
以下代码
i==i1输出true,说明i和i1的对象地址相同
f==f1输出false,说明f和f1对象地址不相同
public class Test {
public static void main(String[] args) {
Integer i=127;
Integer i1 = 127;
System.out.println(i == i1);//输出true
Integer f = 128;
Integer f1 = 128;
System.out.println(f == f1);//输出false
}
}
128陷阱的解释
我们打开JDK1.8源码
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #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.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
以上注释翻译为
返回一个表示指定 int 值的 Integer 实例。如果不需要新的 Integer 实例,则通常应优先使用此方法而不是构造函数 Integer(int),因为此方法可能会通过缓存频繁请求的值来显着提高空间和时间性能。此方法将始终缓存 -128 到 127(含)范围内的值,并且可能缓存此范围之外的其他值。
通俗易懂点解释就是,Java作者知道我们大部分人用数字大概率只用-128到127之间的数字,所以给我们创建了一个数组,范围在-128到127之间,这样可以大大地减少空间和时间性能.
代码的意思为:我们每次使用Integer这个类的时候,都会提前调用这个valueOf(int i)方法,如果我们输入的数字i比 i >= IntegerCache.low && i <= IntegerCache.high,也就是比-128大,比127小,就会返回IntegerCache.cache[]数组中的第i + (-IntegerCache.low)元素,如果不符合条件,就会new一个新的Integer对象,这也就是为什么f==f1显示的为false,因为这是两个不同的对象
那我们再看Integer中的IntegerCache类
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
以上注释翻译为
缓存以支持 JLS 要求的 -128 和 127(含)之间的值的自动装箱的对象标识语义。缓存在第一次使用时被初始化。缓存的大小可以由 -XX:AutoBoxCacheMax=<size> 选项控制。在VM初始化时,可以设置java.lang.Integer.IntegerCache.high属性并保存在sun.misc.VM类的私有系统属性中。
通俗易懂点解释就是,给我们创建了一个范围从-128到127的缓存数组cache[]