Java 为什么 == 与 Integer.valueOf(String) 的比较给出 127 和 128 的不同结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20877086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do == comparisons with Integer.valueOf(String) give different results for 127 and 128?
提问by DnR
I have no idea why these lines of code return different values:
我不知道为什么这些代码行返回不同的值:
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"));
The output is:
输出是:
true
false
true
Why does the first one return true
and the second one return false
? Is there something different that I don't know between 127
and 128
? (Of course I know that 127
< 128
.)
为什么第一个返回true
而第二个返回false
?有什么不同,我不知道之间127
和128
?(我当然知道127
< 128
.)
Also, why does the third one return true
?
另外,为什么第三个返回true
?
I have read the answer of this question, but I still didn't get how it can return true
, and why the code in second line returns false
.
我已经阅读了这个问题的答案,但我仍然不明白它是如何返回的true
,以及为什么第二行中的代码返回false
。
采纳答案by Makoto
There's a striking difference here.
这里有一个显着的不同。
valueOf
is returning an Integer
object, which may have its values cached between -128 and 127. This is why the first value returns true
- it's cached - and the second value returns false
- 128 isn't a cached value, so you're getting two separate Integer
instances.
valueOf
正在返回一个Integer
对象,它的值可能缓存在 -128 和 127 之间。这就是为什么第一个值返回true
- 它被缓存 - 第二个值返回false
- 128 不是一个缓存值,所以你得到两个单独的Integer
实例.
It is important to notethat you are comparing references with Integer#valueOf
, and if you are comparing a value that is larger than what the cache supports, it will notevaluate to true
, even if the parsed values are equivalent (case in point: Integer.valueOf(128) == Integer.valueOf(128)
). You mustuse equals()
instead.
重要的是要注意,您正在与 比较引用Integer#valueOf
,并且如果您比较的值大于缓存支持的值,即使解析的值相等(例如:) ,它也不会计算为。您必须使用来代替。true
Integer.valueOf(128) == Integer.valueOf(128)
equals()
parseInt
is returning a primitive int
. This is why the third value returns true
- 128 == 128
is evaluated, and is of course, true
.
parseInt
正在返回一个原语int
。这就是为什么第三个值返回true
-128 == 128
被评估,当然是true
.
Now, a fair bit happens to make that third result true
:
现在,相当多的事情发生了第三个结果true
:
An unboxing conversion occurswith respect to the equivalence operator you're using and the datatypes you have - namely,
int
andInteger
. You're getting anInteger
fromvalueOf
on the right hand side, of course.After the conversion, you're comparing two primitive
int
values. Comparison happens just as you would expect it to with respect to primitives, so you wind up comparing128
and128
.
拆箱转换发生在您使用的等价运算符和您拥有的数据类型 - 即
int
andInteger
。你得到一个Integer
从valueOf
右手边的,当然。转换后,您将比较两个原始
int
值。比较的发生正如您对原语所期望的那样,因此您最终比较128
和128
。
回答by Nambi
Integer objects caches between -128 and 127 of 256 Integer
整数对象缓存在 -128 和 127 之间,共 256 个整数
You should not compare object references with ==or !=. You should use .equals(..)instead, or better - use the primitive int rather than Integer.
您不应将对象引用与==或!=进行比较。你应该使用 . equals(..)相反,或者更好 - 使用原始 int 而不是 Integer。
parseInt: Parses the string argument as a signed decimal integer. The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value. The resulting integer value is returned, exactly as if the argument and the radix 10 were given as arguments to the parseInt(java.lang.String, int) method.
parseInt:将字符串参数解析为带符号的十进制整数。字符串中的字符必须全部为十进制数字,除了第一个字符可以是 ASCII 减号 '-' ('\u002D') 表示负值。返回结果整数值,就像参数和基数 10 作为参数提供给 parseInt(java.lang.String, int) 方法一样。
valueOfReturns an Integer object holding the value extracted from the specified String when parsed with the radix given by the second argument. The first argument is interpreted as representing a signed integer in the radix specified by the second argument, exactly as if the arguments were given to the parseInt(java.lang.String, int) method. The result is an Integer object that represents the integer value specified by the string.
valueOf返回一个 Integer 对象,其中包含使用第二个参数给出的基数解析时从指定 String 中提取的值。第一个参数被解释为表示由第二个参数指定的基数中的有符号整数,就像将参数提供给 parseInt(java.lang.String, int) 方法一样。结果是一个 Integer 对象,表示由字符串指定的整数值。
equivalent to
相当于
new Integer(Integer.parseInt(s, radix))
radix - the radix to be used in interpreting s
radix - 用于解释 s 的基数
so if you equal Integer.valueOf()
for the integer inbetween
所以如果你等于Integer.valueOf()
中间的整数
-128 to 127 it returns true in your condition
-128 到 127 它在您的条件下返回 true
for lesser than
-128 and greater than
127 it gives false
对于 lesser than
-128 和greater than
127,它给出false
回答by Dawood ibn Kareem
The Integer
class has a static cache, that stores 256 special Integer
objects - one for every value between -128 and 127. With that in mind, consider the difference between these three.
本Integer
类有一个静态缓存器,存储256个特殊的Integer
对象-一个用于记-128和127.这之间的每一个值,考虑这三者之间的区别。
new Integer(123);
This (obviously) makes a brand new Integer
object.
这(显然)创建了一个全新的Integer
对象。
Integer.parseInt("123");
This returns an int
primitive value after parsing the String
.
这int
在解析String
.
Integer.valueOf("123");
This is more complex than the others. It starts off by parsing the String
. Then, if the value is between -128 and 127, it returns the corresponding object from the static cache. If the value is outside of this range, then it invokes new Integer()
and passes in the value, so that you get a new object.
这比其他的更复杂。它首先解析String
. 然后,如果该值介于 -128 和 127 之间,则从静态缓存中返回相应的对象。如果该值超出此范围,则它会调用new Integer()
并传入该值,以便您获得一个新对象。
Now, consider the three expressions in the question.
现在,考虑问题中的三个表达式。
Integer.valueOf("127")==Integer.valueOf("127");
This returns true, because the Integer
whose value is 127 is retrieved twice from the static cache, and compared to itself. There's only one Integer
object involved, so this returns true
.
这将返回 true,因为Integer
其值为 127 的 将从静态缓存中检索两次,并与自身进行比较。只Integer
涉及一个对象,因此返回true
.
Integer.valueOf("128")==Integer.valueOf("128");
This returns false
, because 128 is not in the static cache. So a new Integer
is created for each side of the equality. Since there are two different Integer
objects, and ==
for objects only returns true
if both sides are the exact same object, this is going to be false
.
这将返回false
,因为 128 不在静态缓存中。因此Integer
,为等式的每一侧都创建了一个新的。由于有两个不同的Integer
对象,并且==
对于对象仅true
当双方是完全相同的对象时才返回,这将是false
.
Integer.parseInt("128")==Integer.valueOf("128");
This is comparing the primitive int
value 128 on the left, with a newly created Integer
object on the right. But because it doesn't make sense to compare an int
to an Integer
, Java will auto-unbox the Integer
before doing the comparison; so you end up comparing an int
to an int
. Since the primitive 128 is equal to itself, this returns true
.
这是将int
左侧的原始值 128 与右侧的新创建Integer
对象进行比较。但是因为将 anint
与 an进行比较没有意义,Integer
所以Integer
在进行比较之前,Java 将自动拆箱;所以你最终将 anint
与 an进行比较int
。由于基元 128 等于自身,因此返回true
。
回答by piobab
Take care of returning values from these methods. The valueOfmethod returns an Integer instance:
注意这些方法的返回值。该的valueOf方法返回一个整数实例:
public static Integer valueOf(int i)
The parseIntmethod returns integer value (primitive type):
的parseInt函数的整数值(原始类型)方法返回:
public static int parseInt(String s) throws NumberFormatException
Explanation for comparison:
比较说明:
In order to save memory, two instances of the wrapper objects , will always be == when their primitive values are the same:
- Boolean
- Byte
- Character from \u0000 to \u007f (7f is 127 in decimal)
- Short and Integer from -128 to 127
When == is used to compare a primitive to a wrapper, the wrapper will be unwrapped and the comparison will be primitive to primitive.
为了节省内存,包装对象的两个实例,当它们的原始值相同时,总是 == :
- 布尔值
- 字节
- 从 \u0000 到 \u007f 的字符(7f 是十进制的 127)
- 从 -128 到 127 的短整数和整数
当 == 用于比较一个原语和一个包装器时,包装器将被解包并且比较将是原语对原语的。
In your situation (according to the above rules):
在您的情况下(根据上述规则):
Integer.valueOf("127")==Integer.valueOf("127")
This expression compares references to the same object because it contains Integer value between -128 and 127 so it returns true
.
此表达式比较对同一对象的引用,因为它包含介于 -128 和 127 之间的整数值,因此它返回true
。
Integer.valueOf("128")==Integer.valueOf("128")
This expression compares references to different objects because they contain Integer values not in <-128, 127> so it returns false
.
此表达式比较对不同对象的引用,因为它们包含不在 <-128, 127> 中的整数值,因此它返回false
。
Integer.parseInt("128")==Integer.valueOf("128")
This expression compares primitive value (left hand side) and reference to the object (right hand side)
so right hand side will be unwrapped and his primitive type will be compared to the left so it returns true
.
此表达式比较原始值(左侧)和对对象的引用(右侧),因此右侧将被解包,其原始类型将与左侧进行比较,因此返回true
。
回答by higuaro
To complement the given answers, also take note of the following:
为了补充给出的答案,还请注意以下几点:
public class Test {
public static void main(String... args) {
Integer a = new Integer(129);
Integer b = new Integer(129);
System.out.println(a == b);
}
}
This code will also print: false
此代码还将打印: false
As user Jayhas claimed in a comment for the accepted answer, care must be taken when using operator ==
on objects, here you're checking if both references are the same, which is not, because they are different objets, although they represent the very same value. To compare objects, you should use the equals
method instead:
正如用户Jay在对已接受答案的评论中声称的那样,==
在对象上使用运算符时必须小心,在这里您要检查两个引用是否相同,事实并非如此,因为它们是不同的对象,尽管它们代表了非常相同的值。要比较对象,您应该使用该equals
方法:
Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a.equals(b));
This will print: true
这将打印: true
You may ask, But then why the first line printed true
?. Checking the source code for the Integer.valueOf
method, you can see the following:
你可能会问,那为什么打印第一行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);
}
If the param is an integer between IntegerCache.low
(defaulted to -128) and IntegerCache.high
(calculated at runtime with minimum value 127) then a pre-allocated (cached) object is returned. So when you use 127 as parameter, you're getting two references to same cached object and getting true
in the comparison of the references.
如果 param 是IntegerCache.low
(默认为 -128)和IntegerCache.high
(在运行时以最小值 127 计算)之间的整数,则返回预分配(缓存)对象。因此,当您使用 127 作为参数时,您将获得对同一缓存对象的两个引用,并true
进行引用的比较。