这种奇怪的Java行为的原因是什么?

时间:2012-08-14 17:58:36

标签: java jvm bytecode

我想测试Long上的'=='运算符,这就是我发现的:以下代码:

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]内,并将其地址提供给Long s以及在上面的范围内,它为代码中遇到的每个静态值创建一个新的分配。

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

PS。我知道我应该使用null检查,然后使用.equals()来比较对象,但如果有人知道答案,我很好奇。

修改

jtahlborn 的回答中,谁给了我关键字自动拳击后,我发现这篇精彩的文章与well-documented answer

3 个答案:

答案 0 :(得分:6)

这是自动装箱的结果。请参阅Long.valueOf()

答案 1 :(得分:3)

Long有一个内部缓存,用于-128到127之间的值。如果您通过Long方法创建Long.valueOf(long)或在此时间间隔内自动装箱,则始终会为equals值接收相同的对象。这就是为什么'=='在你的例子中适用于0,127和-128。

如果在[-128,127]之外创建Long,则始终会在Long对象时创建新实例。 这就是'=='不适用于128和-129的原因。

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

答案 2 :(得分:1)

如果您是-128 to +127,则使用==运算符将

comparing object references评估为true。 Long值(从-128到+127)放在缓存中并多次返回,而每次更高和更低的数字都会生成new Long

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