我遇到了一个有趣(而且非常令人沮丧)的问题,equals()
今天的方法导致了我认为是经过良好测试的类崩溃并导致我花了很长时间才能追踪的错误.
为了完整起见,我没有使用IDE或调试器 - 只是老式的文本编辑器和System.out.时间非常有限,这是一个学校项目.
无论如何 -
我开发一个基本的购物车可能包含ArrayList
的Book
对象.为了贯彻落实addBook()
,removeBook()
以及hasBook()
对车的方法,我想检查是否Book
已在存在Cart
.我走了 -
public boolean equals(Book b) { ... // More code here - null checks if (b.getID() == this.getID()) return true; else return false; }
一切都在测试中运行良好.我创建了6个对象并用数据填充它们.做了很多添加,删除,has()操作Cart
,一切正常.我读到你可以拥有equals(TYPE var)
或者equals(Object o) { (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); }
突然间,该equals(Book b)
方法不再有效.这需要花费很长时间才能在没有良好调试器的情况下进行跟踪,并假设Cart
该类已经过适当的测试和更正.将equals()
方法交换到以下内容后:
public boolean equals(Object o) { Book b = (Book) o; ... // The rest goes here }
一切都开始了.有没有理由该方法决定不采用Book参数,即使它显然是一个Book
对象?唯一的区别似乎是它是在同一个类中实例化的,并且只填充了一个数据成员.我很困惑.请揭开一些光明?
在Java中,equals()
继承的方法Object
是:
public boolean equals(Object other);
换句话说,参数必须是类型Object
.
在ArrayList
使用正确的equals方法,在那里你总是调用一个没有适当覆盖Object
的平等.
不正确覆盖方法可能会导致问题.
我每次都重写等于以下内容:
@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
注释可以帮助减轻愚蠢的错误.
只要您认为自己覆盖了超类或接口的方法,就可以使用它.这样,如果你做错了,你将收到编译错误.
如果您使用eclipse,请转到顶部菜单
Source - >生成equals()和hashCode()
对你的问题稍微偏离主题,但无论如何它可能值得一提:
Commons Lang有一些很好的方法可以用来覆盖equals和hashcode.查看EqualsBuilder.reflectionEquals(...)和HashCodeBuilder.reflectionHashCode(...).过去让我感到很头疼 - 虽然当然如果你只是想对ID做"等于"它可能不适合你的情况.
我同意你应该@Override
在覆盖equals(或任何其他方法)时使用注释.