如安在Java中避免equals办法的躲藏陷阱[Java编程]
本文“如安在Java中避免equals办法的躲藏陷阱[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
译者注 :你大概会认为Java很简单,Object的equals实现也会非常简单,但是事实并非你想象的这样,耐烦的读完本文,你会发现你对Java理解的是如此的少.假如这篇文章是一份Java程序员的入职笔试,那么不知道有多少人会掉落到这样的陷阱中.
择要
本文描写重载equals办法的技术,这种技术即便是具现类的子类增添了字段也能保证equal语义的精确性.
在《Effective Java》的第8项中,Josh Bloch描写了当担当类作为面向对象语言中的等价关系的底子问题,要保证派生类的equal精确性语义所会面对的艰难.Bloch这样写到:
除非你忘掉了面向对象抽象的好处,不然在当你担当一个新类或在类中增添了一个值组件时你无法同时保证equal的语义仍然精确
在《Programming in Scala》中的第28章演示了一种办法,这种办法答应即便担当了新类,增添了新的值组件,equal的语义仍旧能得到保证.固然在这本书中这项技术是在利用Scala类环境中,但是这项技术一样可以利用于Java定义的类中.在本文中的描写来自于Programming in Scala中的文字描写,但是代码被我从scala翻译成了Java
常见的等价办法陷阱
java.lang.Object 类定义了equals这个办法,它的子类可以通太重载来覆盖它.不幸的是,在面向对象中写出精确的equals办法是非常艰难的.事实上,在研究了大量的Java代码后,2007 paper的作者得出了以下的一个结论:
几近全部的equals办法的实现都是错误的!
这个问题是因为等价是和很多其他的事物相关联.比方此中之一,一个的范例C的错误等价办法大概意味着你无法将这个范例C的对象可托赖的放入到容器中.比方说,你有两个元素elem1和elem2他们都是范例C的对象,并且他们是相等,即elem1.equals(elm2)返回ture.但是,只要这个equals办法是错误的实现,那么你就有大概会瞥见以下的一些行为:
Set hashSet<C> = new java.util.HashSet<C>();
hashSet.add(elem1);
hashSet.contains(elem2); // returns false!
当equals重载时,这里有4个会引发equals行为不一致的常见陷阱:
定义了错误的equals办法签名(signature) Defining equals with the wrong signature.
重载了equals的但没有同时重载hashCode的办法. Changing equals without also changing hashCode.
成立在会改变字域上的equals定义. Defining equals in terms of mutable fields.
不满意等价关系的equals错误定义 Failing to define equals as an equivalence relation.
在剩下的章节中我们将顺次谈论这4中陷阱.
陷阱1:定义错误equals办法签名(signature)
考虑为下面这个简单类Point增添一个等价性办法:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
// ...
}
以上是“如安在Java中避免equals办法的躲藏陷阱[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |