为什么在比较 Java 中的整数包装器时 128==128 为假而 127==127 为真?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1700081/
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 is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
提问by vipin k.
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
Output:
输出:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
Output:
输出:
true
Note: Numbers between -128 and 127 are true.
注意:-128 和 127 之间的数字是正确的。
采纳答案by Andreas Petersson
When you compile a number literal in Java and assign it to a Integer (capital I
) the compiler emits:
当您在 Java 中编译数字文字并将其分配给 Integer (capital I
) 时,编译器会发出:
Integer b2 =Integer.valueOf(127)
This line of code is also generated when you use autoboxing.
当您使用自动装箱时,也会生成这行代码。
valueOf
is implemented such that certain numbers are "pooled", and it returns the same instance for values smaller than 128.
valueOf
实现了某些数字被“合并”,并且它返回小于 128 的值的相同实例。
From the java 1.6 source code, line 621:
来自 java 1.6 源代码,第 621 行:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
The value of high
can be configured to another value, with the system property.
的值high
可以通过系统属性配置为另一个值。
-Djava.lang.Integer.IntegerCache.high=999
-Djava.lang.Integer.IntegerCache.high=999
If you run your program with that system property, it will output true!
如果您使用该系统属性运行您的程序,它将输出 true!
The obvious conclusion: never rely on two references being identical, always compare them with .equals()
method.
显而易见的结论:永远不要依赖两个引用是相同的,总是用.equals()
方法比较它们。
So b2.equals(b3)
will print true for all logically equal values of b2,b3.
因此,b2.equals(b3)
对于 b2,b3 的所有逻辑上相等的值,将打印 true。
Note that Integer
cache is not there for performance reasons, but rather to conform to the JLS, section 5.1.7; object identity must be given for values -128 to 127 inclusive.
请注意,Integer
缓存不是出于性能原因,而是为了符合JLS,第 5.1.7 节;必须为值 -128 到 127(含)提供对象标识。
Integer#valueOf(int)also documents this behavior:
Integer#valueOf(int)也记录了这种行为:
this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
通过缓存频繁请求的值,此方法可能会产生明显更好的空间和时间性能。此方法将始终缓存 -128 到 127(含)范围内的值,并且可能缓存此范围之外的其他值。
回答by Michael Lloyd Lee mlk
Autoboxing caches -128 to 127. This is specified in the JLS (5.1.7).
自动装箱缓存 -128 到 127。这是在 JLS ( 5.1.7) 中指定的。
If the valuep being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
如果被装箱的值p是真、假、一个字节、一个 \u0000 到 \u007f 范围内的字符,或者一个 int 或 -128 到 127 之间的短数,那么让 r1 和 r2 是任何两个装箱转换的结果p. 的 r1 == r2 总是如此。
A simple rule to remember when dealing with objects is - use .equals
if you want to check if the two objects are "equal", use ==
when you want to see if they point to the same instance.
处理对象时要记住的一个简单规则是 -.equals
如果要检查两个对象是否“相等”,请使用,==
在要查看它们是否指向同一实例时使用。
回答by chrisbunney
Using primitive data types, ints, would produce true in both cases, the expected output.
在这两种情况下,使用原始数据类型 int 都会产生 true,即预期的输出。
However, since you're using Integer objects the == operator has a different meaning.
但是,由于您使用的是 Integer 对象,因此 == 运算符具有不同的含义。
In the context of objects, == checks to see if the variables refer to the same object reference.
在对象的上下文中,== 检查变量是否引用相同的对象引用。
To compare the value of the objects you should use the equals() method E.g.
要比较对象的值,您应该使用 equals() 方法 例如
b2.equals(b1)
which will indicate whether b2 is less than b1, greater than, or equal to (check the API for details)
这将指示 b2 是否小于 b1、大于或等于(查看 API 了解详细信息)
回答by thejartender
I wrote the following as this problem isn't just specific to Integer. My conclusion is that more often than not if you use the API incorrectly, you sill see incorrect behavior. Use it correctly and you should see the correct behavior:
我写了以下内容,因为这个问题不仅特定于 Integer。我的结论是,如果您不正确地使用 API,通常会看到不正确的行为。正确使用它,您应该会看到正确的行为:
public static void main (String[] args) {
Byte b1=127;
Byte b2=127;
Short s1=127; //incorrect should use Byte
Short s2=127; //incorrect should use Byte
Short s3=128;
Short s4=128;
Integer i1=127; //incorrect should use Byte
Integer i2=127; //incorrect should use Byte
Integer i3=128;
Integer i4=128;
Integer i5=32767; //incorrect should use Short
Integer i6=32767; //incorrect should use Short
Long l1=127L; //incorrect should use Byte
Long l2=127L; //incorrect should use Byte
Long l3=13267L; //incorrect should use Short
Long l4=32767L; //incorrect should use Short
Long l5=2147483647L; //incorrect should use Integer
Long l6=2147483647L; //incorrect should use Integer
Long l7=2147483648L;
Long l8=2147483648L;
System.out.print(b1==b2); //true (incorrect) Used API correctly
System.out.print(s1==s2); //true (incorrect) Used API incorrectly
System.out.print(i1==i2); //true (incorrect) Used API incorrectly
System.out.print(l1==l2); //true (incorrect) Used API incorrectly
System.out.print(s3==s4); //false (correct) Used API correctly
System.out.print(i3==i4); //false (correct) Used API correctly
System.out.print(i5==i6); //false (correct) Used API correctly
System.out.print(l3==l4); //false (correct) Used API correctly
System.out.print(l7==l8); //false (correct) Used API correctly
System.out.print(l5==l6); //false (correct) Used API incorrectly
}
回答by yanghaogn
Have a look at the Integer.java, if the value is between -128 and 127, it will use the cached pool, so (Integer) 1 == (Integer) 1
while (Integer) 222 != (Integer) 222
看看Integer.java,如果值在-128到127之间,就会使用缓存池,所以(Integer) 1 == (Integer) 1
虽然(Integer) 222 != (Integer) 222
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
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);
}
回答by Developer Marius ?il?nas
It is memory optimization in Java related.
它与 Java 中的内存优化有关。
To save on memory, Java 'reuses' all the wrapper objects whose values fall in the following ranges:
All Boolean values (true and false)
All Byte values
All Character values from \u0000 to \u007f (i.e. 0 to 127 in decimal)
All Short and Integer values from -128 to 127.
为了节省内存,Java 会“重用”所有值在以下范围内的包装器对象:
所有布尔值(真和假)
所有字节值
从 \u0000 到 \u007f 的所有字符值(即十进制 0 到 127)
从 -128 到 127 的所有短整型和整型值。