java中一个容易忽视的问题

(本文参考importNew的文章(http://www.importnew.com/22386.html),向原文作者致敬。)
问题描述:请问如下代码输出是什么?
Integer a = 1000, b = 1000; 
System.out.println(a == b);
Integer c = 100, d = 100; 
System.out.println(c == d);
代码输出的结果为:
false
true
为什么会输出这样的结果?这是个有趣且很容易被人忽略的问题,很多人包括我一开始就理所当然的认为输出的是两个true,但是后来反复的研究了一下,才发现了其中奥秘。
我们知道,如果两个引用指向同一个对象,那么==就成立;反之,如果两个引用指向的不是同一个对象,那么==就不成立,即便两个引用的内容是一样的。因此,结果就会出现false。这是非常有趣的地方。如果你查看Integer.java类,你会找到IntegerCache.java这个内部私有类,它为-128到127之间的所有整数对象提供缓存。这个东西为那些数值比较小的整数提供内部缓存,当进行如此声明时:
Integer c = 100;
它的内部就是这样的:
Integer i = Integer.valueOf(100);
如果我们观察valueOf()类函数,我们可以看到:
public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }
如果值在-128到127之间,它就会返回该缓存的实例。
所以Integer c = 100, d = 100指的就是同一个对象。
现在你可能会问,为什么会为-128到127之间的所有整数设置缓存?
这是因为在这个范围内的小数值整数在日常生活中的使用频率要比其它的大得多,多次使用相同的底层对象这一特性可以通过该设置进行有效的内存优化。你可以使用reflection API任意使用这个功能。
运行下面的这段代码,你就会明白它的神奇所在了。
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //获取Integer中的cache
        Class cache = Integer.class.getDeclaredClasses()[0]; //1
        Field myCache = cache.getDeclaredField("cache"); //2
        myCache.setAccessible(true);//3
        //将Integer的cache放在新的Integer[]中
        Integer[] newCache = (Integer[]) myCache.get(cache); //4
        for (int i = 0; i < newCache.length; i++) {
            System.out.println("index"+i+":"+newCache[i]);
        }
        System.out.println("index132:"+newCache[132]);//output:4
        System.out.println("index133:"+newCache[133]);//output:5
        System.out.println(newCache[132] = newCache[133]);//output:5
        newCache[132] = newCache[133]; //5
        //在Integer缓存值得范围内创建对象并计算
        int a = 2;
        System.out.printf("%d",a);
        System.out.println();
        int b = a + a;
        System.out.printf("%d",b);
        System.out.println();
        System.out.printf("%d + %d = %d", a, a, b); //
    }

你可能感兴趣的:(java)