【问题标题】:Java - boxing integer - why it return true if should return falseJava - 拳击整数 - 如果应该返回 false,为什么它返回 true
【发布时间】:2015-11-24 08:35:54
【问题描述】:

我在比较两段代码

Integer x = new Integer(0), y;
y=x;
x+=0;
System.out.println(x==y); // prints false

Integer x = 0, y;
y=x;
x+=0;
System.out.println(x==y); // prints true

不应该都返回false吗?它不是原始变量,即使在添加零之后,它也会在第二个代码中以某种方式打印true。我知道拳击(对于从 -128 到 127 的整数),但是为什么拳击在第二段代码中起作用,而不是在第一段代码中起作用?

【问题讨论】:

  • 不,因为-128 - 127 范围内的Integer 正在被缓存。在您的第一个示例中,您明确创建了一个新的Integer,尽管-128 - 127 范围内的每个Integer 都将引用同一个对象。
  • 尽管其他答案说 -128 - 127 不是教条,它只是 JVM 的一个特性,可以在某些具有 -Djava.lang.Integer.IntegerCache.high 属性的版本上进行调整,默认值可能与 JVM 有很大不同JVM,你永远不应该依赖这种行为!stackoverflow.com/questions/15052216/…

标签: java integer boxing


【解决方案1】:

不应该都返回 false 吗?

线

x += 0;

一样
x = Integer.valueOf(x.intValue() + 0);

所以你看到它使用装箱和拆箱来完成操作。


第二个例子只使用了装箱,所以它按预期工作。

在第一个示例中,您明确避免使用

进行装箱
Integer x = new Integer(0);

这会强制它创建一个与装箱对象不同的新对象。

如果你这样做

Integer x = Integer.valueOf(0);

它的行为与第二个示例相同。

【讨论】:

  • 也许如果编译器足够聪明,它可能会忽略 0 的增量?
  • @VinodMadyalkar 是的,但是它有这样的副作用。 Java 非常不愿意破坏兼容性,即使它没有多大意义恕我直言。注意:x += 0f 确实为某些值做了一些事情,也许令人惊讶。
  • 我在评论之前实际上已经考虑过了。但肯定编译器可以在正常情况下做事(就像问题一样):)。这可能会阻止几个字节码指令
  • 哦。可怜的 JIT。它必须完成所有艰苦的工作:P。谢谢你:)
  • @VinodMadyalkar 每次启动 JVM 时:P
【解决方案2】:

不,因为-128 - 127 范围内的整数正在被缓存。在您的第一个示例中,您明确创建了一个新的整数,尽管-128 - 127 范围内的每个整数都将引用同一个对象。

如果您在第一个示例中添加了一些内容,您可以通知这一点。 请注意,这仅适用于-128 - 127 Integer 范围

Integer x = new Integer(0), y;
Integer z = 0; // refers to the cached value.
y=x;
x+=0;
System.out.println(x==z); // This will now print true, since x+=0 will return the cached Integer.

如果您将值 x 更改为不同的值,例如 360,您的第二个示例也将不再有效

【讨论】:

    【解决方案3】:

    [update] 使用new Integer(int) 保证总是产生一个新对象,而Integer.valueOf(int) 允许缓存值由编译器、类库完成, 或 JVM。

    为了解释我写了下面的代码并使用了javap 工具,生成下面的代码的命令我使用了javap -c <Classname>,它给了你字节码。

        Integer x = new Integer(0), y;
        y=x;
        x+=0;
        System.out.println(x==y); // prints false
    

    如果您将在上面的代码中看到,它会使用动态内存分配器 new 创建新对象。现在在第二种情况如下:

        Integer x = 0, y;
        y=x;
        x+=0;
        System.out.println(x==y); // prints true
    

    正如 Peter 所说,它使用 valueOf 方法,这意味着它在运行时比较相同的对象,因此它将返回 true 和对象比较运算符 (==)。但在第一种情况下,它正在创建新对象,这在下面的调试快照中很明显:

    我希望这会有所帮助。 :)

    顺便说一句,Kevin Esche 的回答也增加了问题。因为它基本上是引用缓存的对象,所以在String的情况下尝试关联它。如果您使用new String("some_string"),它将创建新对象,否则如果可用,它将使用string pool。请记住,您使用的不是原始的包装类。

    【讨论】:

      【解决方案4】:

      因为,

      整数 x 是一个对象。 所以 == ,比较的是参考而不是价值。

      int x 不是一个对象 所以 == ,比较值

      你的简单代码:

      Integer x = new Integer(0), y;
      y=x;
      x+=0;
      System.out.println(x==y); // prints false
      System.out.println(x.equals(y)); // prints true
      
      int x1, y1;
      x1 = 5;
      y1 = x1;
      
      System.out.println(x1==y1); // prints true
      System.out.println(((Integer) x1).equals(y1)); //prints true
      

      结果:

      • 是的
      • 是的
      • 是的

      最好的问候

      好的 - 我已经看到了 javap 的响应(感谢您的回答),我明白我想念什么。但是,我发现我提出的这段代码仍然很有趣。

      【讨论】:

      • 我认为你没有得到提问者问题的本质。他很惊讶,为什么第二个例子返回 true。
      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 1970-01-01
      • 2013-09-18
      相关资源
      最近更新 更多