覆盖equals遵守通用约定
- 自反性
- 对称性
- 传递性
- 一致性
- 非空性 非
null
引用值x
,x.equals(null)
返回false
- 判断
Float
或Double
相等使用Float.compare
或者Double.compare
方法,因为存在Float.NaN/-0.0f
以及类似的double
常量
覆盖equals时总要覆盖hashCode
- 相等的对象必须具有相等的散列码
- 不相等的对象产生不相等的散列码
- 覆盖
equals
方法不覆盖hashCode
会导致:该类无法结合基于散列的所有集合(HashMap/HashSet/HashTable
)正常工作
始终要覆盖toString
Object.toString
方法包含类名+“@”+散列码的十六进制表示法- 建议所有的子类都覆盖这个方法
toString
方法需要提供详细的注释或者说明意图toString
返回值中所有信息,每个都要提供访问的方法toString
在文档中指定返回值的格式(有哪些关键的字段),最好提供一个相匹配的静态工厂或者构造器(关键字段作为参数)。java
平台类库中的BigInteger/BigDecimal
和绝大多数的基本类型包装类都采取这种做法。
谨慎的覆盖clone
Cloneable
接口没有任何方法,如果类实现了Caloneable
接口Object
的clone
方法就会该类的逐域拷贝,否则抛出CloneNotSupportedException
- 类每个域中包含一个基本类型的值或者一个指向不可变对象的引用,
super.clone()
返回即可不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects)。
不可变对象的类即为不可变类(Immutable Class)。Java平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。 - 类包含的域引用了可变对象仅仅使用
super.clone
可能会导致灾难性的后果 clone
架构与引用可变对象的final
域的正常用法不兼容- 其他拷贝的办法:拷贝构造器或者拷贝工厂,唯一参数类型是包含该构造器的类
1
2
3
4拷贝构造器:public Yum(Yum yum)
拷贝静态工厂:public static Yum newInstatnce(Yum yum)
参数类型可以是该类实现的接口(转换构造器或转换工厂)允许客户选择拷贝的实现类型。例如参数为接口Set,可以把一个HashSet转换为TreeSet
专家级程序员干脆从来不去覆盖clone方法
考虑实现Comparable接口
compareTo
并没有在object
类中声明- 类实现了
Comparable
接口表明它的实例具有内在的排序关系 Java
平台类库中所有的值类(value classes
实例表示一个值的类)都实现了Comparable
接口- 自定义值类具有非常明显的内在排序关系需要实现这个接口
compareTo
方法通常情况下返回结果应当和equals
方法返回结果相同,即与equals
一致(consistent with equals)
。虽然绝非必要,但是违反此条件应当明确予以说明。- 与
equals
方法不一致(inconsistent with equals)
,违反约定仍能正常工作。集合接口是按equals
方法定义通用约定,但有序集合是按compareTo
方法定义通用约定。如果不一致可能实例在不同的集合中比较结果不相等。例如:new BigDecimal(“1.00”)与new BigDecimal(“1.0”)添加到HashSet中使用equals方法比较结果不想等。
但在TreeSet中使用compareTo方法比较是相等的。