equals()方法实现了等价关系。
-
自反性。对于任何非null的引用值x,x.equals(x)必须返回true.(对象必须等于其自身)
-
对称性。对于任何非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.equeals(z)也必须返回true。(优先使用组合而不是继承,可以避免违反传递性 对称性,否则没有完美解决方案。 只要超类不能直接创建实例,则不会违反原则)
-
一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)返回值一致。()
-
非空性。对于任何非null的引用值x,x.equals(null)必须返回false。(不用重复判空,只需要用instance 即可)
实现高质量equals方法的诀窍:
-
使用==操作符 检查”参数是否为这个对象的引用”。如果是,返回true。这是一种性能优化,适用于比较操作昂贵的情况。
-
使用instanceof操作符检查“参数是否为正确的类型”。如果不是,返回false。
-
把参数强转成正确的类型。
-
对于该类中的每个“关键”域进行匹配比较。(float使用Float.compare()比较,double使用Double.compare()比较。 有些filed可能为null,且合法。 可以用
(field ==null? o.field==null: field.equals(0.field))
。 如果field和o.field通常是相同的对象引用,那么下面的做法更快一些:( field == o.field || field!=null && field.equlas(0.field))
) -
编写完equals方法之后,应该去测试 对称性、传递性、一致性。
-
覆盖equals时,同时覆盖hashCode。
-
不要将equals()方法声明中的Object对象替换为其他的类型。
(public boolean equals(MyClass o)){})
//一个示例
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof EnumSingletonTest)) {
return false;
}
EnumSingletonTest data = (EnumSingletonTest) o;
return data.xxx == xxx
&& dta.bbb == bbb;
}
9 覆盖equals时 总要覆盖 hashCode
不覆盖该方法,会导致该类无法配合HashMap、HashSet和Hashtable一起使用。
因为equals()相等的话,hashCode()一定要相等。
一个好的散列函数通常倾向于“为不相等的对象产生不相等的散列码”。
10 始终要覆盖 toString
11 谨慎地覆盖clone
一般,x.clone() != x
,x.clone().getClass() == x.getClass()
, x.clone().equals(x)
(但也不强求)
实际上,clone方法就是另一个构造器;你必须确保它不会伤害到原始的对象,并确保正确地创建被克隆对象中的约束条件。
更好的办法是类似集合类那样,提供 转换构造器 和 转换工厂。且转换构造器和工厂可以带一个接口类型的参数。 例如你有一个HashSet,想得到TreeSet,clone方法无法提供这样的功能,但是用转换构造器很容易实现。 new TreeSet(s)。
专家级程序员不建议用clone。
12 考虑实现 Comparable 接口
实现compareTo()方法 。它的约定和equals方法相似。(自反、传递、对称),但它不用进行类型检查。比较时,顺序很重要,先比较重要的,如果产生了非零的结果,则结束比较。
小于返回负整数,等于返回0,大于返回正整数。
墙裂建议,(x.compareTo(y)==0) == (x.equals(y))
用于TreeSet TreeMap,以及工具类Collections、Arrays,内部包含搜索和排序算法。
如果一个域没有实现Comparable接口,或者需要使用一个非标准的排序关系。可以用Comparator来代替,或者使用已有的Comparator。例如:
public final class A implements Comparable{
private String s ;
public int compareto(A a){
return String.CASE_INSENSITIVE_ORDER_.compare(s,a.s);
}
}
有些时候可以直接用 this.s - other.s 来作为返回值,但是要确保 最小和最大的可能域值之差小于或等于INTEGER.MAX_VALUE。否则计算结果超过int型溢出时, 结果将相反。
第四章 类和接口
13使类和成员的可访问性最小化
隐藏内部数据和实现细节。
尽可能的使每个类或者成