Java中反射计算2 + 2 = 5

代码如下:
package basic;

import java.lang.reflect.Field;

public class TestField {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        @SuppressWarnings("rawtypes")
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field myCache = cache.getDeclaredField("cache");
        myCache.setAccessible(true);
        Integer[] newCache = (Integer[]) myCache.get(cache);
        newCache[132] = newCache[133];
        int a = 2;
        int b = a + a;
        System.out.printf("%d + %d = %d", a, a, b);
    }
}

运行结果如下:

2 + 2 = 5

为什么会有这样的输出结果呢?

另外附上内部类IntgerCache的源码如下:

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) {
            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);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }
    private IntegerCache() {}
}
阅读 4.1k
3 个回答

JavaInteger对-127到128的整形数据是有缓存的,你这里通过反射缓存中的第133号数据(既整数5)赋值给了第132号数据(既整数4),所以4就会变成5来表示。在使用int数据计算时结果是正常的,但是在打印时由于做了装箱,int数据变成了Integer,这时会采用缓存,所以4就会打印出5来。

我测试了一下,此时System.out.println(Integer.valueOf(4));输出为5
查看Integer.valueOf的源码:

 public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
 }

可以看到是通过下标查找对应的值,也就是找到cache[4 + 128],此时cache[132] = cache[133] = 5;

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏