11

奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?

 2 years ago
source link: http://www.androidchina.net/6158.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True? – Android开发中文站

你的位置:Android开发中文站 > Java基础 > 奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?

这是我们今天要讨论的话题,因为我觉得它非常的有趣。

如果你运行如下代码:

class  A
{
    public static void main(String[] args) 
    {
        Integer a = 128, b = 128;
        System.out.println(a == b);
        Integer c = 127, d = 127;
        System.out.println(c == d);
    }
}

你会得到如下结果:

false
true

这里写图片描述

我们知道,如果两个引用指向同一个对象,那么==就成立;反之,如果两个引用指向的不是同一个对象,那么==就不成立,即便两个引用的内容是一样的。因此,结果就会出现false。

这是非常有趣的地方。如果你查看Integer.Java类,你会找到IntegerCache.java这个内部私有类,它为-128到127之间的所有整数对象提供缓存。

这个东西为那些数值比较小的整数提供内部缓存,当进行如此声明时:

Integer c = 127

它的内部就是这样的:

Integer var3 = Integer.valueOf(127);

其实我通过将A.class文件反编译后,代码如下图:

这里写图片描述

如果我们观察valueOf()类函数,我们可以看到:

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

这里写图片描述

如果值在-128到127之间,它就会返回该缓存的实例。

因此。。。

Integer c = 127, d = 127;

两者指向同样的对象。

这就是为什么下面这段代码的结果为true了:

System.out.println(c == d);

现在你可能会问,为什么会为-128到127之间的所有整数设置缓存?

这是因为在这个范围内的小数值整数在日常生活中的使用频率要比其它的大得多,多次使用相同的底层对象这一特性可以通过该设置进行有效的内存优化。你可以使用reflection API任意使用这个功能。

运行下面的这段代码,你就会明白它的神奇所在了。

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

      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

这里写图片描述

我们再次看一下反汇编代码:

这里写图片描述

是不是又和上面的是同一个问题呢?

但是结果为什么是 2 + 2 = 5 呢?

我们继续去看一下 Integer 源码,去深入了解 Integer 缓存机制,下面截个图:

这里写图片描述

根据源码可以发现最后修改 Integer 缓存上限时候的方法有点小瑕疵。我们看看Api给我们怎么建议的一段话:

the size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.

原来我们只需要:运行时设置 -XX:AutoBoxCacheMax=133 就OK。

转载请注明:Android开发中文站 » 奇怪的Java题:为什么128 == 128返回为False,而127 == 127会返回为True?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK