Java中的整数比较

Java中的整数比较很棘手,因为intInteger行为不同。 我得到那个部分。

但是,正如此示例程序所示, (Integer)400 (第4行)的行为与(Integer)5 (第3行)不同 。 为什么是这样??

 import java.util.*; import java.lang.*; import java.io.*; class Ideone { public static void main (String[] args) throws java.lang.Exception { System.out.format("1. 5 == 5 : %b\n", 5 == 5); System.out.format("2. (int)5 == (int)5 : %b\n", (int)5 == (int)5); System.out.format("3. (Integer)5 == (Integer)5 : %b\n", (Integer)5 == (Integer)5); System.out.format("4. (Integer)400 == (Integer)400 : %b\n", (Integer)400 == (Integer)400); System.out.format("5. new Integer(5) == (Integer)5 : %b\n", new Integer(5) == (Integer)5); } } 

结果

 1. 5 == 5 : true // Expected 2. (int)5 == (int)5 : true // Expected 3. (Integer)5 == (Integer)5 : true // Expected 4. (Integer)400 == (Integer)400 : false // WHAT? 5. new Integer(5) == (Integer)5 : false // Odd, but expected 

来自JLS

如果被装箱的值p为真,假,字节或范围为\ u0000到\ u007f的字符,或介于-128和127(含)之间的整数或短数,则让r1和r2为结果p的任何两个拳击转换。 始终是r1 == r2的情况。

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

这确保了在大多数常见情况下,行为将是期望的行为,而不会造成过度的性能损失,尤其是在小型设备上。 例如,较少内存限制的实现可以缓存所有char和short值,以及-32K到+ 32K范围内的int和long值。

因为在将文字自动装箱到Integer ,评估如下:

 (Integer)400 --- Integer.valueOf(400) 

valueOf is implemented such that certain numbers are "pooled", and it returns the same instance for values smaller than 128.

并且因为(Integer)5小于128,所以它将被合并并且(Integer)400将不被合并。

因此:

 3. (Integer)5 == (Integer)5 : true // Expected -- since 5 is pooled (ie same reference) 

 4. Integer(400) == (Integer)400 : false // WHAT? -- since 400 is not pooled (ie different reference) 

以下是JLS的引用:

如果被装箱的值p为真,假,字节或范围为\ u0000到\ u007f的字符,或介于-128和127(含)之间的整数或短数,则让r1和r2为结果p的任何两个拳击转换。 始终是r1 == r2的情况。

简而言之, Integer使用pool,因此对于从-128到127的数字,你将在装箱后获得相同的对象,例如new Integer(120) == new Integer(120)将评估为true ,但是new Integer(130) == new Integer(130)将评估为false