Java 重写equals方法时,我们是否只使用';对象obj';作为参数?
我的任务是: 在您的应用程序中适当地重写equals()和hashCode()方法 有理数类 它进一步扩展了。我的问题是,当重写equals方法时,是否更改传入的参数?如果它检查逻辑等价性,则我已完成以下操作:Java 重写equals方法时,我们是否只使用';对象obj';作为参数?,java,overriding,equals,Java,Overriding,Equals,我的任务是: 在您的应用程序中适当地重写equals()和hashCode()方法 有理数类 它进一步扩展了。我的问题是,当重写equals方法时,是否更改传入的参数?如果它检查逻辑等价性,则我已完成以下操作: public boolean equals(Rational rhs){ if(this.num == rhs.num && this.denom == rhs.denom){ return true; } return false
public boolean equals(Rational rhs){
if(this.num == rhs.num && this.denom == rhs.denom){
return true;
}
return false;
}
我不确定在重写该方法时这是否是一种方法。如果是,那么当您重写hashcode方法时,是否只是简单地挑选一段好的代码来分配hashcodes
此外,这是我创建的哈希代码。这样做对吗
@Override
public int hashCode(){
int hc = 17;
hc = 37 * hc + ((num == 0 && denom == 0) ? 0 : num);
return 37 * hc + denom;
//boolean b = cond ? boolExpr1 : boolExpr2;
//if cond true then b=boolExpr1 else b=boolExpr2
}
您的
equals
方法不会覆盖对象的equals
。要覆盖它,参数必须是对象
@Override
public boolean equals(Object other){
if (!(other instanceof Rational))
return false;
Rational rhs = (Rational) other;
if(this.num == rhs.num && this.denom == rhs.denom){
return true;
}
return false;
}
请注意,@Override
注释有助于检测您打算重写方法但却重载了该方法的情况。如果您将该注释放在原始方法中,您将得到一个编译错误,因为您的方法没有覆盖任何方法(假设您的Rational
类没有扩展或实现包含boolean equals(Rational rhs)
方法的某个类/接口).但是您可以这样做,因为这不会覆盖等于(对象)
您仍然需要这样做
public boolean equals(Object o) {
return o instanceof Rational && equals((Rational) o);
}
调用equals(Object)
的原因是您可能有许多不同类型的集合
List list = Arrays.asList(1, "Hello", new Rational(1, 2));
// needs to be able to compare with 1 and "Hello"
list.contains(new Rational(1, 2));
要正确重写一个方法—要在针对超类类型的引用调用该方法时“神奇地”调用重写方法—参数类型必须与超类中的参数类型完全相同
<> P>看看为什么会出现这种情况,考虑一下这里会发生什么:
Object r = new Rational();
boolean b = r.equals("x");
我们已经创建了一个对Rational
的对象引用,这是允许我们做的,我们正在向对象传递一个String
。equals(Object)
方法,这也是允许我们做的,因为String是一个对象
如果你的覆盖成功了,你现在就有了一个Rational
对String
对象疯狂的引用!这将打破Java中的类型安全规则。通过强制您的参数为精确匹配,该语言可以确保方法中只出现“可接受”的参数
当然,为了使方法有效,现在需要一个强制显式地将“Obj'”ARG视为一个Rational:<代码> Rational RHS=(Rational)Objr;<代码>-您可能希望事先执行
instanceof
检查,以确保obj实际上是Rational
,而不是其他类型(如字符串!)
一些值得理解的问题:
- 在上面我们称之为
r.equals(“x”)
的情况下:您可能会想“编译器难道不能看到r
实际上指向的是Rational
”?答案是“是”:Java只是选择不这样做。事实是,这是一个简单的例子来证明这一点。一般来说,为了保持一致性,引用类型的规则非常严格,而且通常,编译器无法“看到”这样的情况,比如Rational
作为对象引用被传递到库方法中,或者是对象集合的成员李>
equals
方法有一个中等复杂的契约,值得研究:您应该检查null,担心子类等会发生什么。我在上面使用instanceof
是有争议的-getClass()==obj.getClass()
可能更好。查查——约书亚·布洛赫(Joshua Bloch)的高效Java在这方面非常出色。或者读一下:
- 有一种Java不支持的理论机制,称为“逆变参数覆盖”。这将允许
myMethod(String)
被myMethod(Object)
覆盖(即您可以使用一个更一般的参数-与您的情况相反),该参数始终是安全的,并且不会违反规则。但是它本身会导致问题,Java不支持它;请看下面的答案:
关于实现hashCode()
方法的最后一个问题:在这样一个简单的类中,是的,通用hashCode方法应该可以。通常,将等于
位设置正确是95%的工作
编辑:在更新的问题中,您提供了一个hashCode方法,该方法不。。。想了很多!您可以将其拆分为return(31+num)*31+denom代码>,或类似代码。我之所以使用31是因为:。这是一个等于的重载,而不是覆盖。为了正确实现equals,它必须获得一个类型对象作为parameterOh,然后您将该对象转换为一个Rational,明白了。谢谢
if (obj instanceof Rational) {
Rational r = (Rational)obj;
....