我不知道为什么这些代码行会返回不同的值:
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
?在127
和128
之间是否存在我不知道的不同之处? (当然我知道127
< 128
。)
另外,为什么第三个返回true
?
我已经阅读了答案of this question,但我仍然没有得到它如何返回true
,以及为什么第二行中的代码会返回false
。
答案 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关于您正在使用的等价运算符以及您拥有的数据类型 - 即int
和Integer
。当然,您从右侧Integer
获得valueOf
。
转换后,您要比较两个原始int
值。比较发生就像你对原始的预期一样,所以你最终比较128
和128
。
答案 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
对象进行比较。但是因为将int
与Integer
进行比较没有意义,所以Java会在进行比较之前自动取消对Integer
的打开;因此,您最终会将int
与int
进行比较。由于原语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