java identityHashCode 和 hashCode
阿新 • • 發佈:2020-09-17
當類並沒有重寫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); }