But as per java’s general contact they should return same value.
Java的equals-hashCode契约要求如果两个对象相等于Object.equals,则它们必须具有来自Object.hashCode的相同哈希码.但是Object.equals的默认实现是引用相等,因此当且仅当它们是它们时,两个实例是相同的相同的实例.
因此,特别是,您的两个实例t1和t2实际上并不相等,因为您没有覆盖Object.equals.它们不等于引用,因此每个Object.equals不相等,因此hashCode可能返回不同的值.事实上,合同明确说明如下:
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.
因此,我们在这里没有违反equals-hashCode合约.
因此,对于您的对象,如果您希望不同的实例在相等的逻辑定义中相等,则需要覆盖Object.equals:
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
if (this == obj) {
return true;
}
if (!(obj instanceof Test)) {
return false;
}
Test other = (Test)obj;
return this.i == other.i && this.j == other.j;
}
而且equals-hashCode契约也要求你重写Object.hashCode,否则你会遇到一些讨厌的错误:
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.i;
hash = 31 * hash + this.j;
return hash;
}
合同说什么:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
让我们看看我们是否满足这个要求.如果x和y是Test的实例并且满足x.equals(y)为真,那么我们有x.i == y.i和x.j == y.j.然后,很明显,如果我们调用x.hashCode()和y.hashCode(),我们就有了一个不变量,即在Test.hashCode的每一行执行中,我们将拥有相同值的哈希值.很明显,这在第一行是正确的,因为在两种情况下哈希都是17.它将保持在第二行,因为this.i将返回相同的值,无论是== x还是this == y,因为x.i等于y.i.最后,在倒数第二行,我们仍然会在两次调用中使用哈希值相等,因为x.j等于y.j也是如此.
请注意,我们还没有讨论过最后一部分合同.这是hashCode在单个Java应用程序执行期间返回一致值的要求:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
这一点的必要性是显而易见的.如果在单个执行同一个应用程序期间更改hashCode的返回值,则可能会丢失使用hashCode来跟踪对象的类哈希表数据结构中的对象.特别是,这就是为什么变异像哈希表类数据结构中的键的对象是纯粹的邪恶;不要这样做.我甚至认为它们应该是不可改变的对象.
In fact, when i am doing same thing with String or Integer they are returning same hashcode().
他们都重写了Object.equals和Object.hashCode.