章节3 所有对象通用的方法
10.重写equals时要遵守规范
不需要重写equals的四种情形
- 每个实例都是独一无二的,比如线程Thread
- 不需要判断是否逻辑上相等,比如java.util.regex.Pattern 匹配的是不是同一个模式
- 父类的equals方法适用于子类,子类不需要重写
- 类是私有或包内私有的,你可以保证equals方法不被调用时,但是最保险的还是重写,return一个异常去确保他不会被调用> equals方法的特性
- 反射性:对于非空的引用x,x.equals(x) 必须返回true
- 对称性: x.equals(y) 和y.equal(x)返回值要一样
- 传递性:x=y;x=z
->y=z- 一致性:在没改变比较对象时,结果不能发生改变
- 非空性:对于任何一个非空的引用 x,x.equals(null)必须返回false 一些重写高质量equals方法的技巧
- 使用==判断是否引用同一个对象,可以 优化执行速度
- 使用instanceof方法来检查类型
- 强制转化为正确的类型,因为我们第二部检查过了,保证成功
- 对于这个类的"重要属性",要检查参数的对应属性是否相等
11.重写equals时总是重写hashCode方法
hashCode方法的三个规范
在应用的执行期间,若对象用于比较的信息未发生改变,则返回值必须保持一致
如果俩个对象在equals方法下是相等的,则他们的hashCode方法返回值必须一致
如果俩个对象不相等,他们的hashCode不要求一定不同,但是不同的hashCode会提升哈希表的性能
当你没能重写hashCode方法时,会违反第二条规范
不要为了去提升性能而把重要的属性排除在hashCode之外,这只会导致更多的性能下降,甚至导致hashTable无法正常工作
不要为hashCode的返回值指定明确的规范,客户端无法合理的依赖他,但是可以是你更灵活的改变它
12.总是重写toString方法
提供一个好的toString方法会让你更乐意去使用,并且使得系统更容易debug
事实上,toString方法应该返回对象中所有有用的信息
无论你是否指定返回的格式,你都应该清晰的记录你的意图
并且,你需要提供可以获取返回值中包含信息的方法
总结:
总是去重写每个你所写对象的toString方法,除非父类已经写了,这会使你更乐意去使用并且对debug非常有帮助,toString方法需要以一种美观的格式返回一个简短的,有用的关于这个对象的描述.
13.谨慎的去重写clone方法
尽管文档并没有指明,事实上,如果一个类实现了Cloneable接口,是希望它可以提供一个合适的public clone方法
不可变的类不要为它提供clone方法,避免造成空间的浪费
实际上,clone方法就像一个构造器,你应该保证它不会损害原本的类,并且为clone的类建立合适的不变量
Cloneable接口和一个类的final引用一个可变对象是不兼容的,所以有必要移除需要clone类中引用的final关键字
public clone方法应该忽略抛出异常,因为父类已经抛出了,并且不抛出可查异常的方法更容易使用
clone方法不是线程安全的
总结
对于所有实现cloneable的类必须重写一个 返回值为这个类本身的public clone方法,这个方法首先要调用super.Clone,然后在对需要特殊处理的属性进行处理,既深拷贝
一个对象复制的更好方法就是一个copy构造器或者copy工厂
优势:
- 不依赖高风险的语言之外的对象创建机制
- 不需要去遵守无法强制执行的约定
- 和final关键字并不矛盾
- 不需要抛出没必要的异常
- 而且可以用接口作为参数传入方法,适用性更强
14.考虑实现Comparable
在compareTo中使用><符号容易出错,冗长,不再推荐使用
总结:
无论何时,如果你想要让你写的类有一个合理的排序,你应该去实现一个Comparable接口,这样该实例才能简单的被排序,搜索,在基于比较的集合中被使用,不要使用大于小于号,使用静态的compare方法如:Integer.compare()或者利用在Comparator接口中的比较器构造方法写自己的比较器
从Xmind复制到typora,再从typora的源码复制过来,比直接在这上面改快多了,咋感觉掘金的markdown有点泵比