我的课程包含以下equals()
和hashCode()
方法
@Override
public boolean equals(Object o)
{
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
Phrases that = (Phrases) o;
if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test
if (exitMsg != null ? !exitMsg.equals(that.exitMsg) : that.exitMsg != null)
{ return false; }
if (introMsg != null ? !introMsg.equals(that.introMsg) : that.introMsg != null)
{ return false; }
if (msg != null ? !msg.equals(that.msg) : that.msg != null)
{ return false; }
if (phrase != null ? !phrase.equals(that.phrase) : that.phrase != null)
{ return false; }
if (title != null ? !title.equals(that.title) : that.title != null)
{ return false; }
return true;
}
@Override
public int hashCode()
{
int result = phrase != null ? phrase.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (introMsg != null ? introMsg.hashCode() : 0);
result = 31 * result + (msg != null ? msg.hashCode() : 0);
result = 31 * result + (exitMsg != null ? exitMsg.hashCode() : 0);
return result;
}
我试图找出为什么 clover 无法告诉我的哈希码方法已经运行。我添加了一行:
if (this.hashCode() == o.hashCode()) { return true; } //retry clover coverage test
根据三叶草每次等于方法运行if (this == o) { return true; }
false 但if (this.hashCode() == o.hashCode()) { return true; }
true 。
问题:
为什么this == o
和this.hashCode() == o.hashCode()
没有评估相同的结果?
答案 0 :(得分:5)
根据定义,哈希码包含的信息少于源数据。这意味着碰撞是可能的,在这种情况下,您将拥有两个具有相同哈希码但不相等的对象。
Java hashCode()
的一般要求是相反的方向:
equals
关系所持有的两个对象必须生成相同的哈希码(相反的情况并非如此)基本上关键是你不能将哈希码用作唯一标识符(事实上JDK数据结构在内部管理冲突)。
这与==
没有任何关系,因为它只比较了对象的引用(内存地址),hashCode()
和equals将完全相同。
如果你看看你的hashCode()
,你可以看到,如果除了一个字段之外的所有字段都为空,但是哪个字段不同,则计算的哈希码是相同的,这清楚地证明了你可以轻松地产生碰撞。
如果你想要更强大的东西,你应该考虑使用MessageDigest
,它产生的摘要比int
长得多(因此能够容纳更多信息=不太可能发生碰撞)。但即使有他们也不会有任何保证。
答案 1 :(得分:0)
==
不会致电.equals
。
实际上,两者完全不同,仅在未覆盖Object的默认(不良)实现的对象中重叠。
==
只是检查太多的对象是否是等效的指针。
.equals
会运行与您展示的方法类似的方法。
用==
替换.equals
可以解决您的问题
答案 2 :(得分:0)
退一步......
考虑equals()
和hashCode()
的合同。考虑一下合同只是单向的事实:如果你在一个类中实现两者,那么要求是如果一个类的两个实例相等,那么它们必须具有相同的哈希码。
它没有说的是,如果两个实例具有相同的哈希码,那么它们必须相等。但是你假设你的.equals()实现了!
然而在你的代码中,有:
// WRONG!
if (this.hashCode() == o.hashCode()) { return true; }
以下是一个完全有效的hashCode()
方法示例:
public int hashCode()
{
return 42;
}
现在,我相信您可以通过.equals()方法查看问题所在......
假设Java 7,这里是你编写这两种方法的方法;因为两者都占null
,所以这很容易(另一方面,你应该尽可能避免使用null
;最终,null
只不过是麻烦了):
@Override
public final int hashCode()
{
return Objects.hash(phrase, title, introMsg, msg, errorMsg);
}
@Override
public final boolean equals(final Object obj)
{
if (obj == null)
return false;
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
final MyClass other = (MyClass) obj;
return Objects.equals(phrase, other.phrase)
&& Objects.equals(title, other.title)
&& Objects.equals(introMsg, other.introMsg)
&& Objects.equals(msg, other.msg)
&& Objects.equals(errorMsg, other.errorMsg);
}