【问题标题】:Integer comparison in Java [duplicate]Java中的整数比较[重复]
【发布时间】:2015-04-08 12:51:21
【问题描述】:

Java 中的整数比较很棘手,因为 intInteger 的行为不同。我明白了。

但是,正如 example program 所示,(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

【问题讨论】:

标签: java equality boxing


【解决方案1】:

因为在将文字自动装箱到 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 (i.e same reference)

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

【讨论】:

  • 如果是这种情况,那么依赖于 Autoboxing/Unboxing 的代码将会受到影响,这会使代码产生歧义。有点不舒服
【解决方案2】:

这是来自JLS的引用:

如果被装箱的值 p 是真、假、一个字节或 \u0000 到 \u007f 范围内的一个字符,或者一个介于 -128 和 127(含)之间的 int 或短数字,则令 r1 和 r2 为p 的任意两次装箱转换的结果。 r1 == r2 总是如此。

简而言之,Integer 使用池,因此对于从 -128 到 127 的数字,装箱后您将始终得到相同的对象,例如,new Integer(120) == new Integer(120) 的计算结果为 true,但 new Integer(130) == new Integer(130) 的计算结果为 @ 987654326@.

【讨论】:

    【解决方案3】:

    来自JLS

    如果被装箱的值 p 是真、假、一个字节或 \u0000 到 \u007f 范围内的一个字符,或者一个介于 -128 和 127(含)之间的 int 或短数字,则令 r1 和 r2 为p 的任意两次装箱转换的结果。 r1 == r2 总是如此。

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

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

    【讨论】:

      猜你喜欢
      • 2013-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 2016-03-19
      • 2011-08-20
      • 1970-01-01
      相关资源
      最近更新 更多