重写java equals()方法-不工作?
今天,我在重写java equals()方法-不工作?,java,equals,overriding,Java,Equals,Overriding,今天,我在equals()方法中遇到了一个有趣(而且非常令人沮丧)的问题,它导致了我认为是一个经过良好测试的类崩溃,并导致了一个花了我很长时间才发现的bug 为了完整起见,我没有使用IDE或调试器,只是使用了老式的文本编辑器和System.out。时间非常有限,这是一个学校项目 无论如何- 我正在开发一个基本的购物车,它可以包含一个ArrayList的Book对象。为了实现购物车的addBook()、removeBook()和hasBook()方法,我想检查Book是否已经存在于购物车中。所以我
equals()
方法中遇到了一个有趣(而且非常令人沮丧)的问题,它导致了我认为是一个经过良好测试的类崩溃,并导致了一个花了我很长时间才发现的bug
为了完整起见,我没有使用IDE或调试器,只是使用了老式的文本编辑器和System.out。时间非常有限,这是一个学校项目
无论如何-
我正在开发一个基本的购物车,它可以包含一个ArrayList
的Book
对象。为了实现购物车的addBook()
、removeBook()
和hasBook()
方法,我想检查Book
是否已经存在于购物车中。所以我走了-
public boolean equals(Book b) {
... // More code here - null checks
if (b.getID() == this.getID()) return true;
else return false;
}
在测试中一切都很好。我创建了6个对象并用数据填充它们。在购物车上执行许多添加、删除和has()操作,一切正常。我读到你可以有equals(typevar)
或者equals(objecto){(CAST)var}
,但是假设既然它在工作,就没有太大关系了
然后我遇到了一个问题——我需要从Book类中创建一个Book
对象,其中只包含ID
。不会在其中输入其他数据。基本上如下:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
突然间,equals(b书)
方法不再有效。如果没有一个好的调试器,并且假设Cart
类经过了正确的测试,那么跟踪它需要很长时间。将equals()
方法应用于以下对象后:
public boolean hasBook(int i) {
Book b = new Book(i);
return hasBook(b);
}
public boolean hasBook(Book b) {
// .. more code here
return this.books.contains(b);
}
public boolean equals(Object o) {
Book b = (Book) o;
... // The rest goes here
}
一切又开始起作用了。方法决定不接受Book参数,即使它显然是Book
对象,这有什么原因吗?唯一的区别似乎是它是从同一个类中实例化的,并且只填充了一个数据成员。我非常非常困惑。请解释一下?在Java中,继承自对象的equals()
方法是:
public boolean equals(Object other);
换句话说,参数的类型必须是Object
。这被称为覆盖;您的方法public boolean equals(Book other)
对equals()方法执行所谓的重载
ArrayList
使用重写的equals()
方法来比较内容(例如,对于其contains()
和equals()
方法),而不是重载的方法。在大多数代码中,调用没有正确覆盖对象
的equals的函数是可以的,但与数组列表
不兼容
因此,不正确重写该方法可能会导致问题
每次I override等于以下值:
@Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof MyClass)) return false;
MyClass otherMyClass = (MyClass)other;
...test other properties here...
}
使用@Override
注释有助于避免许多愚蠢的错误
只要您认为您正在重写一个超类或接口的方法,就可以使用它。那样的话,如果你用错误的方法,你会得到一个编译错误。稍微偏离了你的问题主题,但无论如何,这可能值得一提:
有一些很好的方法可以用来重写equals和hashcode。退房并离开。过去帮我省去了很多头疼的事——当然,如果你只是想在身份证上做到“平等”,那可能不适合你的情况
我还同意,无论何时重写equals(或任何其他方法),都应该使用@Override
注释。如果使用eclipse,请转到顶部菜单
源-->生成等于()和
hashCode()
另一个节省样板代码的快速解决方案是。它简单、优雅且可定制。而且不依赖于IDE。比如,
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(of={"errorNumber","messageCode"}) // Will only use this fields to generate equals.
public class ErrorMessage{
private long errorNumber;
private int numberOfParameters;
private Level loggingLevel;
private String messageCode;
请参阅可自定义要在equals中使用的字段。龙目山在这里随处可见。只需将其添加到提供的范围中:
org.projectlombok
龙目
1.14.8
假如
在equals的实现中经常使用instanceOf
语句
这是一个常见的陷阱
问题是使用instanceOf
违反了对称规则:
(object1.equals(object2)==true)
当且仅当(object2.equals(object1))
如果第一个等于true,并且object2是
obj1所属的类,则第二个等号将返回false
如果ob1所属的类被声明为final,那么
问题不会出现,但一般来说,您应该进行以下测试:
this.getClass()!=getClass()代码>如果不是,则返回false,否则返回test
要比较的字段是否相等 在Android Studio中
alt+insert-->equals和hashCode
例如:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Proveedor proveedor = (Proveedor) o;
return getId() == proveedor.getId();
}
@Override
public int hashCode() {
return getId();
}
recordId是对象的属性
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Nai_record other = (Nai_record) obj;
if (recordId == null) {
if (other.recordId != null)
return false;
} else if (!recordId.equals(other.recordId))
return false;
return true;
}
考虑:
Object obj = new Book();
obj.equals("hi");
// Oh noes! What happens now? Can't call it with a String that isn't a Book...
我知道我违反了关于通过反射重写equals方法的“约定”-但是我需要一种快速的方法来检查ArrayList中是否存在对象,而不使用泛型。这是学习Java和equals的一个很好的课程这是支持@Override注释的一个很好的论点。。。如果OP使用@Override,他的编译器会告诉他,他实际上并没有重写父类方法……他从来没有意识到@Override,谢谢!我还想补充一点,重写hashCode()确实应该已经完成,并且可能会更快地发现错误。一些IDE(例如Eclipse)甚至可以根据类成员变量为您自动生成equals()和hashCode()方法。if(!(MyClass的其他实例))返回false如果MyClass
扩展了另一个类,则code>返回false
。但是如果另一个类扩展了MyClass,则不会返回false。equal
不应该少一些矛盾吗?当使用上一个空检查的实例时是多余的。如果您是eclipse用户,您也可以