3

我在 Java (JDK 1.7) 中偶然发现了这一点:

    Integer a = 100;
    Integer b = 100;
    Integer c = 1000;
    Integer d = 1000;

    System.out.println(a == b); //true
    System.out.println(c == d); //false
    System.out.println(new Integer(100) == new Integer(100)); //false
    System.out.println(new Integer(1000) == new Integer(1000)); //false

输出为:真假假假

为什么 a==b 评估为真?这是什么原因?这类似于字符串内部化吗?

4

3 回答 3

6

这类似于字符串内部化吗?

是的 - 基本上所有可以放入一个字节(-128 到 +127)的整数都是 intern 的,因此共享相同的底层对象。较大的不是,因此可能不共享相同的底层对象(这在 JLS 5.1.7 中有所介绍) - 但请注意,如果有人选择,规范中没有任何内容可以防止较大的整数共享相同的底层对象以这种方式实现虚拟机。

我想理由是这个范围内的“较小”整数比较大的整数使用得更多,因此使用相同的底层对象是值得的,以减少潜在的内存占用。

在您的new Integer(100) == new Integer(100)示例中,情况并非如此,因为您正在显式创建新的整数对象,类似于new String("hi") == new String("hi")评估为 false 的方式。

只是为了重新迭代 - 在所有现实世界场景中比较这样的整数时,.equals()应该使用 then (或者最好仍然使用原始整数 == ,除非有使用对象类型的好案例。)

于 2013-09-17T13:17:10.813 回答
1

从 -128 到 127 的值被缓存

java.lang.Integer有一个内部静态类,缓存 -128 到 127 之间的所有 Integer 对象

于 2013-09-17T13:18:04.783 回答
1

这是因为所有的小整数都被缓存了(就像字符串内部化一样),所以当你把它们装箱时你会得到相同的实例。

规范

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

附加说明启发了所做的妥协:

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

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

于 2013-09-17T13:17:03.207 回答