Java hashcode的默认实现为以相同方式构造的对象返回不同的值
我在这里编写一个示例代码:Java hashcode的默认实现为以相同方式构造的对象返回不同的值,java,Java,我在这里编写一个示例代码: public class Test { private int i; private int j; public Test() { // TODO Auto-generated constructor stub } public Test(int i, int j) { this.i=i; this.j=j; } } 现在我创建两个对象,如下所示: Test
public class Test {
private int i;
private int j;
public Test() {
// TODO Auto-generated constructor stub
}
public Test(int i, int j)
{
this.i=i;
this.j=j;
}
}
现在我创建两个对象,如下所示:
Test t1= new Test(4,5);
Test t2 = new Test(4,5);
但是当我打印t1.hashcode()和t2.hashcode()时,它们给出了不同的值。
但根据java的一般联系,它们应该返回相同的值。
事实上,当我对字符串或整数执行相同的操作时,它们返回的是相同的hashcode()。有人能解释为什么t1和t2对象的哈希代码不同吗
但根据java的一般联系,它们应该返回相同的值
Java的equals hashCode
契约要求,如果两个对象的值等于,那么它们必须具有相同的hashCode。但是Object.equals
的默认实现是referenceequality,因此两个实例是相同的当且仅当它们是相同的实例时
因此,特别是,您的两个实例t1
和t2
实际上并不相等,因为您没有重写Object.equals
。它们作为引用不相等,因此每个对象不相等。等于,因此hashCode
可能返回不同的值是可以接受的。事实上,合同明确规定如下:
根据equals(java.lang.Object)
方法,如果两个对象不相等,则对两个对象中的每一个调用hashCode
方法都必须产生不同的整数结果
因此,我们没有违反这里的等于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;
}
而等于hashCode
契约要求您也重写对象。hashCode
,否则您会遇到一些讨厌的bug:
@Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.i;
hash = 31 * hash + this.j;
return hash;
}
合同上怎么说:
如果根据equals(Object)
方法,两个对象相等,那么对两个对象中的每一个调用hashCode
方法必须产生相同的整数结果
让我们看看我们是否满足了这个要求。如果x
和y
是Test
的实例,并且满足x.equals(y)
是true
,我们得到x.i==y.i
和x.j==y.j
。然后,很明显,如果我们调用x.hashCode()
和y.hashCode()
我们有一个不变量,即在Test.hashCode
中的每一行执行时,hash
将保持相同的值。显然,这在第一行是正确的,因为在这两种情况下,hash
都是17
。它将保留在第二行,因为this.i
将返回相同的值,无论this==x
还是this==y
,因为x.i
等于y.i
。最后,在倒数第二行,我们仍然会让hash
在两个调用之间相等,因为x.j
equalsy.j
也是真的
请注意,我们还没有讨论合同的最后一部分。这是要求hashCode
在Java应用程序的单个执行期间返回一致的值:
在Java应用程序的执行过程中,每当在同一对象上多次调用它时,hashCode
方法必须一致地返回相同的整数,前提是不修改对象上的equals比较中使用的信息
这样做的必要性是显而易见的。如果在同一应用程序的单个执行过程中更改hashCode
的返回值,则可能会丢失使用hashCode
跟踪对象的类似哈希表的数据结构中的对象。特别是,这就是为什么在类似哈希表的数据结构中改变作为键的对象是纯粹的邪恶;不要这样做。我甚至认为它们应该是不变的对象
事实上,当我对String
或Integer
执行相同操作时,它们返回的是相同的hashcode()
它们都重写了Object.equals
和Object.hashCode
这是因为Java中默认实现了equals
和hashCode
JVM无法知道如何确定两个对象是相同的。它所做的是使用内存引用。因此,默认情况下,等于
和hashCode
方法比较内存引用;i、 e.两个不同的对象是从不。等于
如果要覆盖此行为(例如,如果希望使用Collection
s,建议您这样做)然后,您需要做的就是实现自己的equals
和hashCode
方法。您还没有覆盖类中的equals
方法,因此将使用属于对象的默认方法。
对象类方法只是检查引用是否引用同一对象
Test t1 = new Test(4,5);
Test t2 = new Test(4,5);
是两个不同的对象,如果不重写此处的equals
方法,则当且仅当您重写时,它们才会相等
Test t2 = t1;
当您在这里创建两个不同的对象时,hashcode不相等,因为它们引用的对象不同,hashcodes
必须不同
记得吗
- 如果两个对象相等,则它们的hashcode
必须相等
- 但是如果hashcode是相等的,那么对象就没有必要相等
问题在于t1和t2不是同一个对象,而是不同的对象。使用“新建”创建的所有对象都是不同的对象。默认的hashCode()实现通常会为不同的对象返回不同的哈希代码。请参阅Object.hashCode API。您是否阅读了d