java identityHashCode 和 hashCode

当类并没有重写Object#hashCode()时, 对于 System.identityHashCode(Object) 和 Object#hashCode() 的结果是一致的;

但对于类似String这些重写了Object#hashCode()的类时,当直接调用hashCode()时,由于重载的存在,因此调用的是子类中的方法;

对于这种情况,当我们需要获取对象的hashCode时

  1. 方法一:我们可以使用 System.identityHashCode(Object) 来直接获取对象的hashCode
  2. 方法二:可以通过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);
    }

  

posted @ 2020-09-17 17:14  郭星  阅读(347)  评论(0)    收藏  举报