对象引用的哈希码和等于?

Hashcode and Equals for object reference?

我有点小众需要关闭通用类型 XY 的两个对象,并将其用于 return 类型 T。我想将这些项目放在严格管理的 HashMap 中,并用它来查找 X、Y 键。

但是,我如何确保 XY 在它们的内存引用上进行哈希编码和相等性比较,而不是 hashCode/equals 的任何重写实现?

public final class BiReferenceCache<X,Y,T> { 
    private final HashMap<Key<X,Y>,T> cacheMap = new HashMap<>();

    public T get(X item1, Y item2) { 
        return cacheMap.get(new Key<X,Y>());
    }

    private static final class Key<X,Y> { 
        private final X val1;
        private final Y val2;

        Key(X val1, Y val2) { 
            this.val1 = val1;
            this.val2 = val2;
        }

        public int hashCode() { 
            //??? What do I do to hashcode by val1 and val2's memory reference?
        }
        public boolean equals(Object obj) { 
            //??? What do I do to check equality for val1 and val2's memory reference?
        }
    }

}

使用

System.identityHashCode

==

你应该使用 hashCode:

val1.hashCode() + val2.hashCode();

对于等于:

val1.equals(obj.val1) && val2.equals(obj.val2);

基本是推卸责任

PS:如果允许为空,则必须添加适当的代码。

您可以使用 == 检查内存标识并使用 java.lang.System#identityHashCode(Object) 获取未覆盖的哈希码。

private static final class Key<X,Y> { 
    private final X val1;
    private final Y val2;

    Key(X val1, Y val2) { 
        this.val1 = val1;
        this.val2 = val2;
    }

    public int hashCode() { 
        return 31 * System.identityHashCode(val1) + System.identityHashCode(val2);
    }

    public boolean equals(Object obj) { 
        if (obj == null) {
            return false;
        }
        if (!obj instanceof Key) {
            return false;
        }
        Key other = (Key)obj;
        return val1 == other.val1 && val2 == other.val2;
    }
}

== 运算符不应该断言引用相等吗?

这个问题可能会回答您的 hashCode 问题:How do you get the "object reference" of an object in java when toString() and hashCode() have been overridden?(引述如下)

您究竟打算用它做什么(您想做什么会影响您需要调用的内容)?

hashCode(),如 Javadocs 中所定义:

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

因此,如果您使用 hashCode 来确定它是否是内存中的唯一对象,这不是一个好方法。

System.identityHashCode 执行以下操作:

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

其中,您正在做的事情听起来像您想要的...但是您想要做的事情可能并不安全,具体取决于库的实现方式。

对于 hashCode(),您可以简单地使用:val1.hashCode() ^ val2hashCode(); (按字节异或运算符 ^)- 不是一个很好的解决方案,但是它应该做的。

在 equals() 中,您应该首先检查两个对象是否具有相同的引用(使用 ==),然后检查您正在比较的对象是否不为空。之后,确保两个对象都是同一类型的实例。最后一步:检查两者的属性值是否相等。

如果您有一个超类,处理超类中的前 3 个步骤被认为是一种很好的风格。