3、对于所有对象都通用的方法(一)
8、?覆盖equals时请遵守通用约定
如果类具有自己特定的“逻辑相等”概念(不同于对象等同概念),而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖equals方法,这通常属于“值类”的情形,例如Integer或者是Data,程序员在利用equals方法来比较值对象的引用时,希望知道它们在逻辑上是否相等,而不是想了解它们是否指向同一个对象。
?
在覆盖equals方法时,你必须要遵守它的通用约定。下面是约定的内容,来自Object的规范:
??自反性:对于任何非null的引用值x,x.equals(x)必须返回true。如果自已不等于自己的话,将其放入集合中后,该集合的contains方法将告诉你,集合中不包括你刚添加的实例。
??对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。这就要求不同类的实例如果在逻辑值相同的情况下,要求这两个实例所对应的类的equals方法比较逻辑要相同,不然的话,对称性将不再满足。
??传递性:对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
??一致性:对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)就会一致地返回true,或者一致地返回false。
??非空性:对于任何非null的引用值x,x.equals(null)必须返回false。
?
实现高质量的equals方法:
1、?使用==操作符检查“参数是否为这个对象的引用”。如果是,则返回true,这只不过是一种性能优化,如果比较操作有可能很昂贵,就值得这么做。
2、?使用instanceof操作符检查“参数是否为正确的类型”。如果不是,则返回false。一般说来所谓“正确的类型”是指定equals所在的那个类。有些情况下,是指该类所实现的某个接口。如果类实现的接口改进了equals约定,允许在实现了该接口的类之间进行比较,那么就使用接口。集合接口如Set、List、Map和Map.Entry具有这样的特性。注,这步会过滤掉null,因为 null instanceof XX 一定会返回false。
3、?把参数转换成正确的类型。因为转换之前进行过instanceof测试,所以确保会成功。
4、?对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,则返回true,否则返回false。
对于既不是float也不是double类型的基本类型域,可以使用==操作符进行比较;对于对象引用域,可以递归地调用equals方法;对于float域,可以使用Float.compare方法;对于double域,则使用Double.compare。对于数组域,则要把以上这些指导原则应用到每个元素上,如果数组域中的每个元素都需要比较的话,可以使用1.5版本中发行的Arrays.equals方法。
对于float和double域进行特殊的处理是有必要的,因为存在着Float.NaN、-0.0f以及类似的double常量,详细信息请参考Float.equals的文档,看看Float.equals源码与文档描述:
private volatile int hashCode; // (See Item 71)@Override public int hashCode() { int result = hashCode; if (result == 0) { result = 17; result = 31 * result + areaCode; result = 31 * result + prefix; result = 31 * result + lineNumber; hashCode = result; } return result;}
?
1 楼 duaixj_zhu 2010-10-29 effective java 这本书上的内容?有点影响,可惜技术不够就去看那本书了 现在很多地方有些模糊。希望等到楼主的建议去看什么资料好一些?