Java 中的奇怪整数框

2022-08-31 08:19:43

我刚刚看到类似这样的代码:

public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a == b);

        Integer c = 100, d = 100;
        System.out.println(c == d);
    }
}

运行后,此代码块将打印出来:

false
true

我理解为什么第一个是:因为这两个对象是独立的对象,所以比较引用。但是我不明白,为什么第二个语句会返回?当整数的值在一定范围内时,是否有一些奇怪的自动装箱规则?这是怎么回事?false==true


答案 1

该行实际上是由语言规范保证的。从第 5.1.7 节开始:true

如果被装箱的值 p 是 true、false、一个字节、一个介于 \u0000 到 \u007f 范围内的 char,或者是一个介于 -128 和 127 之间的整数或短数字,则让 r1 和 r2 成为 p 的任意两个装箱转换的结果。总是 r1 == r2。

讨论还在继续,这表明虽然你的第二行输出是有保证的,但第一行不是(见下面引用的最后一段):

理想情况下,对给定的基元值 p 进行装箱,将始终产生相同的引用。在实践中,使用现有的实现技术可能不可行。上述规则是务实的妥协。上面的最后一个子句要求始终将某些公共值装箱到无法区分的对象中。实现可能会懒惰或急切地缓存这些。

对于其他值,此公式不允许对程序员的盒装值的标识进行任何假设。这将允许(但不要求)共享部分或全部这些引用。

这可确保在大多数情况下,行为将是所需的行为,而不会造成不适当的性能损失,尤其是在小型设备上。例如,较少的内存限制实现可能会缓存所有字符和短整,以及 -32K - +32K 范围内的整数和长整型。


答案 2
public class Scratch
{
   public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;  //1
        System.out.println(a == b);

        Integer c = 100, d = 100;  //2
        System.out.println(c == d);
   }
}

输出:

false
true

是的,第一个输出是为比较参考而产生的;“a”和“b” - 这是两个不同的参考。在第1点中,实际上创建了两个引用,它们类似于 -

Integer a = new Integer(1000);
Integer b = new Integer(1000);

产生第二个输出是因为尝试保存内存,当落在一个范围(从-128到127)内。在第 2 点,没有为 'd' 创建 Integer 类型的新引用。它不是为 Integer 类型引用变量 'd' 创建新对象,而是仅使用 'c' 引用的先前创建的对象进行赋值。所有这些都是由 完成的。JVMIntegerJVM

这些内存节省规则不仅适用于整数。为了节省内存,以下包装器对象的两个实例(通过装箱创建时)将始终为 ==,其中它们的基元值相同 -

  • 布尔
  • 字节
  • \u0000 到 (7f 在十进制中为 127) 的字符\u007f
  • -128127 的短整型和整数

推荐