我有一个名为 Xpto 的抽象类和两个扩展它的子类,名为 Person 和 Car 。我还有一个名为测试的类,其中包含main()和一个方法 foo(),用于验证两个人或汽车(或类的任何扩展Xpto的对象)是否为等于。因此,我在Person和Car类中重新定义了 equals()。当两个人姓名相同时,两个人是平等的,当他们有相同的登记时,两个车是相同的。
但是,当我在Test类中调用foo()时,我总是得到“false”。我理解为什么:在Xpto抽象类中没有重新定义equals()。那么......我如何在foo()方法中比较两个人或汽车(或者扩展Xpto的类的任何对象)?
总之,这是我的代码:
public abstract class Xpto {
}
public class Person extends Xpto{
protected String name;
public Person(String name){
this.name = name;
}
public boolean equals(Person p){
System.out.println("Person equals()?");
return this.name.compareTo(p.name) == 0 ? true : false;
}
}
public class Car extends Xpto{
protected String registration;
public Car(String registration){
this.registration = registration;
}
public boolean equals(Car car){
System.out.println("Car equals()?");
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
public class Teste {
public static void foo(Xpto xpto1, Xpto xpto2){
if(xpto1.equals(xpto2))
System.out.println("xpto1.equals(xpto2) -> true");
else
System.out.println("xpto1.equals(xpto2) -> false");
}
public static void main(String argv[]){
Car c1 = new Car("ABC");
Car c2 = new Car("DEF");
Person p1 = new Person("Manel");
Person p2 = new Person("Manel");
foo(p1,p2);
}
}
答案 0 :(得分:4)
正如其他人所说,你覆盖的方法的签名必须完全相同。覆盖方法时,为了确保覆盖,请使用函数上方的@Override
注释,因此如果您更改了方法,Eclipse之类的IDE会发出警告。
这就是它的样子:
@Override
public boolean equals(Object obj){
...Your code here...
}
我建议覆盖hashCode()
,因为当将项目插入到列表,集合,hastables等中时......使用相等(和performande)hashCode()
(有时equals()
不是!)
所以你的最终代码是:
@Override
public boolean equals(Object obj){
...Your code here...
}
@Override
public int hashCode(){
...Your code here...
}
的更多信息
答案 1 :(得分:2)
我理解为什么:equals()不是 在Xpto抽象类中重新定义。
实际上equals()
未在代码中的任何地方重新定义 。要覆盖它,您的方法必须将Object
作为参数类型,并且必须将其强制转换(在使用instanceof
进行测试之后,在比较两个不同子类的实例时返回false
。 / p>
答案 2 :(得分:1)
您是否需要public boolean equals(Object o)
作为两个类中的方法签名?
答案 3 :(得分:1)
Javadoc表示您需要使用object作为参数覆盖equals方法。
指示是否有其他对象 “等于”这个。
因此,您的子类equals方法应如下所示:
public class Car extends Xpto
{
protected String registration;
public Car(String registration)
{
this.registration = registration;
}
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (obj == this)
{
return true;
}
if (!obj.getClass().isAssignableFrom(getClass()))
{
return false;
}
Car car = (Car) obj;
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
答案 4 :(得分:1)
声明public boolean equals(Person p)或public boolean equals(Car p)不会覆盖Object的public boolean equals(Object o),它只是一个永远不会被调用的新方法。
答案 5 :(得分:1)
您的equals方法应如下所示:
@Override public boolean equals(Object o) {
if (!(o instanceof YourType)) {
return false;
}
YourType yt = (YourType)o;
... // rest here
}
此外,不要忘记覆盖hashCode
,以便能够在集合中正确使用您的类型。
答案 6 :(得分:1)
通常很难/不可能完全实现等于合同,并且层次结构中仍然有两个不同的类彼此相等,并且通常不会这样做。通常,equals方法测试该类是否相同(因此相同子类的两个实例将彼此相等,但两个不同子类的两个实例将不相同)。
但是,在您的情况下,可以在Xpto中实现等于,因为只有一个属性。显而易见的方法是在Xpto中定义一个抽象方法,然后在Xpto中重写equals:
public class Xpto {
protected abstract String getIdentity();
@Override
public boolean equals(Object o) {
if (o == null) return false;
//Typical implementation
//if (getClass() != o.getClass()) return false;
if (!(o instanceof Xpto)) return false; //risky implementation, but will allow a car to compare to a person
return getIdentity().equals((Xpto) o.getIdentity());
}
@Override
public int hashCode() {
return getIdentity().hashCode();
}
}
其他人已经指出你实际上没有覆盖equals。将来,您可以使用@Override注释让编译器帮助您解决这个问题。在你的情况下,你会早点得到一个编译错误,这会节省你一些时间。
答案 7 :(得分:0)
以下是我的意思:
public abstract class Xpto {
}
public class Person extends Xpto{
protected String name;
public Person(String name){
this.name = name;
}
public boolean equals(Object o){
if(o == null || !getClass().equals(o.getClass())
return false;
Person p = (Person) o;
System.out.println("Person equals()?");
return this.name.compareTo(p.name) == 0 ? true : false;
}
}
public class Car extends Xpto {
protected String registration;
public Car(String registration){
this.registration = registration;
}
public boolean equals(Object o){
if(o == null || !getClass().equals(o.getClass())
return false;
Car car = (Car) o;
System.out.println("Car equals()?");
return this.registration.compareTo(car.registration) == 0 ? true : false;
}
}
public class Teste {
public static void foo(Xpto xpto1, Xpto xpto2){
if(xpto1.equals(xpto2))
System.out.println("xpto1.equals(xpto2) -> true");
else
System.out.println("xpto1.equals(xpto2) -> false");
}
public static void main(String argv[]){
Car c1 = new Car("ABC");
Car c2 = new Car("DEF");
Person p1 = new Person("Manel");
Person p2 = new Person("Manel");
foo(p1,p2);
}
}
每个类都从equals(Object)
类继承Object
方法。因此,Xpto
不需要定义这样的方法。
当在子类中重写此方法时(即:Person
,Car
),必须使用完全相同的签名来定义它。换句话说,equals
方法的参数必须是Object
类型,方法实现必须将其向下转。
答案 8 :(得分:0)
您没有覆盖equals()
方法,而是重载它。将签名更改为
public boolean equals(Object o)
然后将o投射到Person / Car并进行比较。
顺便说一句,您可以将字符串与equals()
进行比较:
return registration.equals(car.registration);
答案 9 :(得分:0)
你的子类定义了equals(Person)或equals(Car),它们都不会像传递Xpto那样。如果你将它们声明为等于(Xpto),或者更好地等于(对象),这样它们就可以在集合中工作,那么你的问题就会消失。
注意,如果你用这种方式重新声明equals()方法,(1)你需要检查你传递的对象的类,因为你不能保证它们不再是汽车或人,而且( 2)你可能也想覆盖getHashCode(),特别是如果你决定使它们都为equals(Object),因为getHashCode()应该为两个相等的对象返回相同的哈希码。