今天看到stackoverflow中有个一非常有意思的问题,特把它翻译出来收藏。StackOverflow原帖地址为http://stackoverflow.com/questions/20877086/confusion-in-method-integer-valueofstring/ .

问题是这样的:

System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));

输出的却是:

true
false
true

问题解决:

Interger类的valueOf返回的是Integer对象。默认情况下,如果参数在-128到127之间,则返回缓存中的对象,否则返回new Integer(int)。它在JDK5中具体实现如下:

   private static class IntegerCache 
   {
      private IntegerCache(){}

      static final Integer cache[] = new Integer[-(-128) + 127 + 1];

      static 
      {
        for(int i = 0; i < cache.length; i++)
        cache[i] = new Integer(i - 128); 
      }
    }

    public static Integer valueOf(int i) 
    {
       final int offset = 128;
       if (i >= -128 && i <= 127) // must cache 
           { 
           return IntegerCache.cache[i + offset];
       }
           return new Integer(i);
    }

而在JDK6中它的具体实现:

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

也就是说我们可以设置系统属性 java.lang.Integer.IntegerCache.high修改缓冲区上限,默认为127。那么如何修改这个上限呢?我们可以在启动程序时,我们需要给虚拟机加参数:

java -Djava.lang.Integer.IntegerCache.high=300 Main

这样也就解决了为什么第1条语句返回true了,因为他们的数值小于等于127,所以都是引用IntegerCache的同一个值为127的Integer对象,所以相等。而128由于大于127,没有了缓存机制,则引用不同的对象,所以不等。如果想判断两个Integer对象的值相不相等,请使用equals()函数。

但是第三条语句System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));为什么相等呢?这是因为parseInt()返回基本类型int,在需要比较时,右边的Integer对象发生拆箱操作也返回基本类型int,基本类型int进行比较,返回true。

References

  1. http://openhome.cc/Gossip/JavaEssence/BoxUnBox.html 写的非常好的文章!
  2. http://stackoverflow.com/questions/20877086/confusion-in-method-integer-valueofstring/20877115

Fork me on GitHub