比较Java中的整数值,奇怪的行为

与我同行 ..

Integer x = 23; Integer y = 23; if (x == y) System.out.println("what else"); // All is well as expected else System.out.println("..."); 

 Integer x = someObject.getIndex(); Integer y = someOtherObject.getSomeOtherIndex(); if (x == y) System.out.println("what else"); else System.out.println("..."); // Prints this 

嗯…我尝试铸造到诠释

 int x = someObject.getIndex(); int y = someOtherObject.getSomeOtherIndex() if (x == y) System.out.println("what else"); // works fine else System.out.println("..."); 

他们都是整数?

 System.out.println(x.getClass().getName()); // java.lang.Integer System.out.println(y.getClass().getName()); // java.lang.Integer System.out.println(someObject.getIndex()); // java.lang.Integer System.out.println(someOtherObject.getSomeOtherIndex()); // java.lang.Integer 

你们有什么感想? 什么会解释这样的事情?

您正在比较Integer数值,它们是引用。 你通过自动装箱提出这些引用。 对于某些值(保证为-128到127),JRE维护一个Integer对象的caching。 对于更高的值,它不会。 从JLS第5.1.7节 :

如果p的值是真,假,一个字节,或者范围在\ u0000到\ u00f之间的一个字符,或者在-128到127之间的一个int或者一个短数字,那么让r1和r2是任何两个拳击转换的p。 r1 == r2总是如此。

理想情况下,装箱一个给定的原始值p,总会产生一个相同的参考。 实际上,使用现有的实现技术可能是不可行的。 上面的规则是一个务实的妥协。 上面的最后一个条款要求某些常用值总是被装入不可区分的对象中。 实现可能会caching这些,懒惰或热切。 对于其他的值,这个公式不允许对程序员的盒装值的身份进行任何假设。 这将允许(但不要求)分享这些引用的一部分或全部。

这确保了在大多数情况下,行为将是所期望的,而不施加不适当的性能损失,特别是在小型设备上。 例如,内存限制较less的实现可能会caching所有char和short值,以及-32K到+ 32K范围内的int和long值。

道德:当你对底层的int值感兴趣时,不要比较Integer引用。 使用.equals()或首先获取int值。

为了正确地比较整数,你需要使用.equals()或者通过强制转换为int或者调用intValue()来比较它们的原始值。

使用==检查两个整数是否是相同的对象 ,而不是它们是否包含相同的数值

  Integer a = new Integer(1); Integer b = new Integer(1); System.out.println(a.equals(b)); //true System.out.println((int)a == (int)b); //true System.out.println(a.intValue() == b.intValue()); //true System.out.println(a == b); //false 

编辑来说明Jon JLS关于自动装箱的观点:

  Integer a = 1; Integer b = 1; System.out.println(a.equals(b)); //true System.out.println((int)a == (int)b); //true System.out.println(a.intValue() == b.intValue()); //true System.out.println(a == b); //true 

与:

  Integer a = 128; Integer b = 128; System.out.println(a.equals(b)); //true System.out.println((int)a == (int)b); //true System.out.println(a.intValue() == b.intValue()); //true System.out.println(a == b); //false 

听起来像是在使用==两个整数时自动装箱的东西。

我会假设,如果你使用equals()方法使用Integer ,它工作正常吗? 无论如何,这将是我的猜测。

你没有使用Java 1.4或者你是什么东西?