4

L的代码很简单

public class L {
}

public class Synchronized1 {
    public static void main(String[] args) {
        L l=new L();
//       System.out.println(l.toString());
       System.out.println(ClassLayout.parseInstance(l).toPrintable());
    }
}

取消注释,再次运行代码会导致不同的结果,或者两个完全不同的结果。我想知道这个结果的原因是什么?不仅调用 toString() 会影响结果,而且在对象上调用其他方法也会影响结果,例如 hashCode()

toString() 评论后

4

1 回答 1

4

您的空类class L使用默认toString()继承自class Object.

默认toString()调用hashCode().

正如您已经看到的那样,hashCode()似乎也影响了对象的标题。

所以,从本质上讲,这个问题可以重述为“为什么调用hashCode()会改变我的对象的标题?”

正如其他人已经在评论中指出的那样,这是因为在您使用的特定 JVM 实现中,对象的 hashCode 在第一次hashCode()被调用时被计算,然后它被缓存在标头中,以便后续调用hashCode()可以只返回缓存的值,而无需再次重新计算。

除了性能之外,这样做可能还有一个更重要的原因。

根据您使用的 JVM 计算哈希码的方式,计算中可能涉及随机性,或者可能存在不断增加的数字种子,因此后续尝试重现对象的哈希码可能没有办法生成与第一次计算完全相同的值。这意味着第一次计算必须确定哈希码值将永远是什么。

于 2019-09-25T14:02:44.220 回答