当类并没有重写Object#hashCode()时, 对于 System.identityHashCode(Object) 和 Object#hashCode() 的结果是一致的;
但对于类似String这些重写了Object#hashCode()的类时,当直接调用hashCode()时,由于重载的存在,因此调用的是子类中的方法;
对于这种情况,当我们需要获取对象的hashCode时
方法一:我们可以使用 System.identityHashCode(Object) 来直接获取对象的hashCode
方法二:可以通过MethodHandle 来调用被子类重载的父级的方法
public void identityHashCodeVsHashCode() throws Throwable {
Object o = new Object();
// 对于Object对象 而言;System.identityHashCode 和 Object#hashCode是相同的
assert System.identityHashCode(o) == o.hashCode();
// 对于 s1 和 s2 实际都是引用的 META区域中相同的对象
String s1 = "1";
String s2 = "1";
assert System.identityHashCode(s1) == System.identityHashCode(s2);
String s3 = new String("1");
assert s1.hashCode() == s3.hashCode();
// 对于s1 和 s3 实际是两个不同的对象, 但由于 String重写了Object#hashCode()
// 当需要对比对象时,我们并不能直接调用到Object#hashCode(),因此只能通过System.identityHashCode来获取对象的hashcode
assert System.identityHashCode(s1) != System.identityHashCode(s3);
// 获取指定类的构造方法并执行
Object object = MethodHandles.lookup().findConstructor(Object.class, MethodType.methodType(void.class)).invoke();
// 获取指定类的方法并绑定指定的对象
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(Object.class, "hashCode", MethodType.methodType(int.class)).bindTo(s3);
Object invoke = methodHandle.invoke();
System.out.println((int)invoke);
assert (int)invoke == System.identityHashCode(s3);
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章