提问人:vipin k. 提问时间:11/9/2009 最后编辑:Steve Chambersvipin k. 更新时间:2/4/2022 访问量:62059
为什么在比较 Java 中的整数包装器时,128==128 是假的,而 127==127 是真的?
Why is 128==128 false but 127==127 is true when comparing Integer wrappers in Java?
问:
class D {
public static void main(String args[]) {
Integer b2=128;
Integer b3=128;
System.out.println(b2==b3);
}
}
输出:
false
class D {
public static void main(String args[]) {
Integer b2=127;
Integer b3=127;
System.out.println(b2==b3);
}
}
输出:
true
注意:介于 -128 和 127 之间的数字为 true。
答:
自动装箱缓存 -128 到 127。这在 JLS (5.1.7) 中指定。
如果装箱的值 p 为 true、false、字节、\u0000 到 \u007f 范围内的字符,或者介于 -128 和 之间的 int 或短整型数字 127,则设 R1 和 R2 是任意两个装箱转换的结果 的 p。r1 == r2 总是如此。
在处理对象时要记住的一个简单的规则是 - 如果要检查两个对象是否“相等”,请使用,如果要查看它们是否指向同一实例,请使用。.equals
==
评论
当您在 Java 中编译一个数字文本并将其分配给 Integer(大写字母)时,编译器会发出:I
Integer b2 =Integer.valueOf(127)
使用自动装箱时也会生成此代码行。
valueOf
实现时,某些数字被“池化”,并且它为小于 128 的值返回相同的实例。
从 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);
}
可以使用系统属性将 的值配置为另一个值。high
-Djava.lang.Integer.IntegerCache.high=999
如果使用该系统属性运行程序,它将输出 true!
显而易见的结论是:永远不要依赖两个相同的参考文献,总是将它们与方法进行比较。.equals()
因此,对于 b2,b3 的所有逻辑相等值,将打印 true。b2.equals(b3)
请注意,缓存不是出于性能原因,而是为了符合 JLS,第 5.1.7 节;必须为值 -128 到 127(含 128 到 127)提供对象标识。Integer
Integer#valueOf(int) 也记录了此行为:
此方法可能会通过缓存经常请求的值来显著提高空间和时间性能。此方法将始终缓存 -128 到 127 范围内的值(包括 128 到 127),并可能缓存此范围之外的其他值。
评论
false
在这两种情况下,使用原始数据类型 ints 都会产生预期的输出 true。
但是,由于您使用的是 Integer 对象,因此 == 运算符具有不同的含义。
在对象的上下文中,== 检查变量是否引用相同的对象引用。
要比较对象的值,您应该使用 equals() 方法 例如
b2.equals(b1)
这将指示 b2 是否小于 b1、大于或等于 (有关详细信息,请查看 API)
我写了以下内容,因为这个问题不仅特定于 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
}
看看 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);
}
它与Java中的内存优化有关。
为了节省内存,Java “重用”了所有包装器对象,其值 属于以下范围:
所有布尔值(true 和 false)
所有 Byte 值
从 \u0000 到 \u007f 的所有字符值(即十进制为 0 到 127)
从 -128 到 127 的所有 Short 和 Integer 值。
其他答案描述了为什么可以观察到观察到的效果,但对于程序员来说,这真的无关紧要(当然很有趣,但在编写实际代码时你应该忘记这一切)。
若要比较 Integer 对象是否相等,请使用该方法。equals
不要尝试使用标识运算符 .==
可能会发生一些相等值是相同对象的情况,但这不是通常应该依赖的东西。
如果该值介于 -128 和 127 之间,它将使用缓存池,并且仅在自动装箱时才成立。 因此,您将拥有以下内容:
public static void main(String[] args) {
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b); // false. == compare two instances, they are difference
System.out.println(a.equals(b)); // true. equals compares the value
Integer a2 = 100;
Integer b2 = 100;
System.out.println(a2 == b2); // true. auto-boxing uses cached pool between -128/127
System.out.println(a2.equals(b2)); // true. equals compares the value
Integer a3 = 129;
Integer b3 = 129;
System.out.println(a3 == b3); // false. not using cached pool
System.out.println(a3.equals(b3)); // true. equals compares the value
}
}
评论