为什么==与Integer.valueOf(String)的比较给出了127和128的不同结果?

时间:2014-01-02 05:49:28

标签: java integer comparison

我不知道为什么这些代码行会返回不同的值:

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

为什么第一个返回true而第二个返回false?在127128之间是否存在我不知道的不同之处? (当然我知道127< 128。)

另外,为什么第三个返回true

我已经阅读了答案of this question,但我仍然没有得到它如何返回true,以及为什么第二行中的代码会返回false

5 个答案:

答案 0 :(得分:187)

这里有一个显着的区别。

valueOf返回一个Integer对象,其值可能在-128到127之间缓存。这就是为什么第一个值返回true - 它被缓存 - 和第二个值返回false - 128不是缓存值,因此您将获得两个单独的Integer个实例。

重要的是要注意您要将引用与Integer#valueOf进行比较,如果您要比较的值大于缓存支持的值,则不< / strong>评估为true,即使解析的值相等(例如:Integer.valueOf(128) == Integer.valueOf(128))。您必须使用equals()代替。

parseInt正在返回原始int。这就是评估第三个值true - 128 == 128的原因,当然是true

现在,有一点恰好会产生第三个结果true

  • An unboxing conversion occurs关于您正在使用的等价运算符以及您拥有的数据类型 - 即intInteger。当然,您从右侧Integer获得valueOf

  • 转换后,您要比较两个原始int值。比较发生就像你对原始的预期一样,所以你最终比较128128

答案 1 :(得分:121)

Integer类有一个静态缓存,它存储256个特殊Integer个对象 - 每个值介于-128到127之间。考虑到这一点,请考虑这三个之间的差异。

new Integer(123);

这显然是一个全新的Integer对象。

Integer.parseInt("123");

在解析int之后返回String原始值。

Integer.valueOf("123");

这比其他人更复杂。它首先解析String。然后,如果该值介于-128和127之间,则它从静态高速缓存返回相应的对象。如果该值超出此范围,则调用new Integer()并传入值,以便获得新对象。

现在,考虑问题中的三个表达式。

Integer.valueOf("127")==Integer.valueOf("127");

返回true,因为值为127的Integer从静态缓存中检索两次,并与自身进行比较。只涉及一个Integer对象,因此返回true

Integer.valueOf("128")==Integer.valueOf("128");

这将返回false,因为128不在静态缓存中。因此,为相等的每一方创建一个新的Integer。由于有两个不同的Integer个对象,而对象==只返回true,如果双方都是完全相同的对象,那么这将是false

Integer.parseInt("128")==Integer.valueOf("128");

这是将左侧的原始int值128与右侧新创建的Integer对象进行比较。但是因为将intInteger进行比较没有意义,所以Java会在进行比较之前自动取消对Integer的打开;因此,您最终会将intint进行比较。由于原语128等于它自己,因此返回true

答案 2 :(得分:13)

注意从这些方法返回值。 valueOf 方法返回Integer实例:

public static Integer valueOf(int i)

parseInt 方法返回整数值(基本类型):

public static int parseInt(String s) throws NumberFormatException

比较说明:

  

为了节省内存,两个实例   包装器对象,总是==当他们的时候   原始值是相同的:

     
      
  • 布尔
  •   
  • 字节
  •   
  • 从\ u0000到\ u007f的字符(7f为十进制127)
  •   
  • 从-128到127
  • 的短整数   
     

当==用于将基元与包装器进行比较时,包装器将是   unwrapped,比较将是原始的。

在您的情况下(根据上述规则):

Integer.valueOf("127")==Integer.valueOf("127")

此expresion比较对同一对象的引用,因为它包含介于-128和127之间的Integer值,因此它返回true。

Integer.valueOf("128")==Integer.valueOf("128")

此表达式比较对不同对象的引用,因为它们包含不在&lt; -128,127&gt;中的整数值。所以它返回false。

Integer.parseInt("128")==Integer.valueOf("128")

此表达式比较原始值(左侧)和对象的引用(右侧) 所以右侧将被解开,他的原始类型将与左侧进行比较,因此它返回true。

答案 3 :(得分:6)

为了补充给定的答案,还要注意以下几点:

public class Test { 
    public static void main(String... args) { 
        Integer a = new Integer(129);
        Integer b = new Integer(129);
        System.out.println(a == b);
    }
}

此代码还将打印:false

当用户Jay在对已接受答案的评论中声明时,在对象上使用运算符==时必须小心,此处您要检查两个引用是否相同,这不是,因为它们是不同的对象,尽管它们代表了相同的价值。要比较对象,您应该使用equals方法:

Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));

这将打印:true

你可能会问,但是为什么第一行打印true。检查Integer.valueOf方法的源代码,您可以看到以下内容:

public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
}

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);
}

如果param是IntegerCache.low(默认为-128)和IntegerCache.high之间的整数(在运行时使用最小值127计算),则返回预分配(缓存)对象。因此,当您使用127作为参数时,您将获得对同一缓存对象的两个引用,并在引用的比较中获得true

答案 4 :(得分:5)

整数对象缓存介于-128和127之间的256 Integer

您不应将对象引用与 == != 进行比较。您应该使用。等于(..),或者更好 - 使用原始int而不是Integer。

parseInt :将字符串参数解析为带符号的十进制整数。字符串中的字符必须全部为十进制数字,除了第一个字符可以是ASCII减号' - '('\ u002D')以指示负值。返回结果整数值,就像参数和基数10作为parseInt(java.lang.String,int)方法的参数一样。

<强>的valueOf 返回一个Integer对象,当使用第二个参数给出的基数进行解析时,该对象保存从指定String中提取的值。第一个参数被解释为表示由第二个参数指定的基数中的有符号整数,就像将参数赋予parseInt(java.lang.String,int)方法一样。结果是一个Integer对象,表示字符串指定的整数值。

相当于

new Integer(Integer.parseInt(s, radix))

radix - 用于解释s

的基数

所以,如果你的整数介于Integer.valueOf()之间

-128到127它在您的条件中返回true

对于lesser than -128和greater than 127,它会false