【问题标题】:What's the cause of this strange Java behavior?这种奇怪的 Java 行为的原因是什么?
【发布时间】:2012-08-14 17:58:35
【问题描述】:

我想在Longs 上测试“==”运算符,这就是我发现的:以下代码:

public static void main(final String[] args) {
    final Long n = 0L;
    final Long m = 0L;
    System.out.println(n + " == " + m + " : " + (n == m));

    final Long a = 127L;
    final Long b = 127L;
    System.out.println(a + " == " + b + " : " + (a == b));

    final Long A = 128L;
    final Long B = 128L;
    System.out.println(A + " == " + B + " : " + (A == B));

    final Long x = -128L;
    final Long y = -128L;
    System.out.println(x + " == " + y + " : " + (x == y));

    final Long X = -129L;
    final Long Y = -129L;
    System.out.println(X + " == " + Y + " : " + (X == Y));
}

输出:

0 == 0 : true
127 == 127 : true
128 == 128 : false
-128 == -128 : true
-129 == -129 : false

我能想到的唯一解释是 JVM 将所有 long 值存储在 Perm 空间中的 [-128, 127] 中,并将它们的地址提供给 Longs 以及上述范围之外的所有内容,它会创建一个新的代码中遇到的每个静态值的分配。

我接近正确了吗?在什么情况下我们必须注意类似的行为?

PS。我知道我应该使用nullcheck 然后.equals() 来比较对象,但我很好奇是否有人知道答案。

编辑

jtahlborn 的回答谁给了我关键字 auto-boxing 之后,我发现这篇很棒的文章带有 well-documented answer

【问题讨论】:

  • 是的,你是对的。 (是的,在这里使用== 而不是.equals 是一种罪过。)
  • 您不应该使用空检查。空检查是邪恶的。只是不要使用 NULL。

标签: java jvm bytecode


【解决方案1】:

这是自动装箱的结果。见Long.valueOf()

【讨论】:

    【解决方案2】:

    Long 有一个内部缓存,用于存储从 -128 到 127 的值。如果您通过 Long.valueOf(long) 方法或在此间隔内自动装箱创建 Long,您总是会收到相同的对象以获得相等的值。这就是为什么 '==' 在您的示例中适用于 0、127 和 -128。

    如果您在 [-128, 127] 之外创建 Long,那么如果 Long 对象,则始终会创建新实例。 这就是为什么 '==' 不适用于 128 和 -129。

    查看Long.valueOf(long) 源代码。

    【讨论】:

      【解决方案3】:

      如果您是comparing object references,则-128 to +127 将使用== 运算符评估为真。 Long 值(从 -128 到 +127)被放入缓存并多次返回,而更大和更低的数字每次生成 new Long

      这也适用于原始包装类Integer, Float。试试 Integer 和 Float。

      【讨论】:

      • 我不是反对者,但我觉得不需要解释 -128 t0 127 将如何为真?
      猜你喜欢
      • 2012-01-05
      • 2019-10-19
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 2017-03-30
      相关资源
      最近更新 更多