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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 04:56:33  来源:igfitidea点击:

Why do == comparisons with Integer.valueOf(String) give different results for 127 and 128?

javaintegercomparison

提问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 trueand the second one return false? Is there something different that I don't know between 127and 128? (Of course I know that 127< 128.)

为什么第一个返回true而第二个返回false?有什么不同,我不知道之间127128?(我当然知道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.

这里有一个显着的不同。

valueOfis returning an Integerobject, 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 Integerinstances.

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,并且如果您比较的值大于缓存支持的值,即使解析的值相等(例如:) ,它也不会计算为。您必须使用来代替。trueInteger.valueOf(128) == Integer.valueOf(128)equals()

parseIntis returning a primitive int. This is why the third value returns true- 128 == 128is 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, intand Integer. You're getting an Integerfrom valueOfon the right hand side, of course.

  • After the conversion, you're comparing two primitive intvalues. Comparison happens just as you would expect it to with respect to primitives, so you wind up comparing 128and 128.

  • 拆箱转换发生在您使用的等价运算符和您拥有的数据类型 - 即intand Integer。你得到一个IntegervalueOf右手边的,当然。

  • 转换后,您将比较两个原始int值。比较的发生正如您对原语所期望的那样,因此您最终比较128128

回答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 than127 it gives false

对于 lesser than-128 和greater than127,它给出false

回答by Dawood ibn Kareem

The Integerclass has a static cache, that stores 256 special Integerobjects - 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 Integerobject.

这(显然)创建了一个全新的Integer对象。

Integer.parseInt("123");

This returns an intprimitive 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 Integerwhose value is 127 is retrieved twice from the static cache, and compared to itself. There's only one Integerobject 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 Integeris created for each side of the equality. Since there are two different Integerobjects, and ==for objects only returns trueif 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 intvalue 128 on the left, with a newly created Integerobject on the right. But because it doesn't make sense to compare an intto an Integer, Java will auto-unbox the Integerbefore doing the comparison; so you end up comparing an intto 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 equalsmethod 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.valueOfmethod, 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 truein the comparison of the references.

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