通过1等于2现象加深对 Integer.IntegerCache
2020-11-27 本文已影响0人
上岸大虾米
IntegerCache 是Integer的内部静态类,包含三个字段,主要目的是缓存指定范围[low-high]的整数,low为-128,high的默认值为127,high可通过JVM参数配置修改,high的最小值为127,cache默认缓存了-128~127范围内的整数
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
}
IntegerCache唯一被Integer.valueOf()方法使用,valueOf()主要是将一个数字赋值给Integer这样的场景使用。例如 Integer a = 3,编译器会将其编译为 Integer a = Integer.valueOf(3)。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
通过valueOf方法源代码了解到,如果参数i的是在cache范围内,则直接返回被缓存的值,否则创建Integer对象,由此引出经常出现的面试题,因此阿里规范推荐使用equals方法比较Integer值是否相同。
Integer c1 = 1;
Integer c2 = 1;
System.out.println(c1 == c2); // true
Integer c3 = 1000;
Integer c4 = 1000;
System.out.println(c3 == c4); // false
缓存部分整形数据,起到复用效果,减少的对象的创建,但是如果随意修改被缓存的值,也会带来一些问题,下面的例子通过修改cache中的值,将会看到 1= 2现象
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class<?>[] declaredClasses = Integer.class.getDeclaredClasses();
Arrays.stream(declaredClasses).forEach(i -> System.out.println(i.getName()));
Class<?> declaredClass = declaredClasses[0];
Field cache = declaredClass.getDeclaredField("cache");
cache.setAccessible(true);
Integer[] cacheArr = (Integer[]) cache.get(null);
System.out.println(cacheArr[129]);
cacheArr[130] = 1;
Integer a = 1;
Integer b = 2;
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true
}