Effective Java-第三章
第3章 对于所有对都通用的方法
尽管Object是一个具体类,但是设计它主要是为了扩展,它所有的非final方法(equals,hashCode,toString,clone和finalize)都有明确的通用约定,因为它们被设计成是要被覆盖的。任何一个类,它在覆盖这些方法的时候,都有责任遵守这些通用约定。如果不能做到这一点,其他依赖于这些约定的类(如HashMap和HashSet)就无法结合该类一起正常工作。
8. 覆盖equals时请遵守通用约定
如果累具有自己特有的“逻辑相等”概念(不同于对象等同的概念),而且超类还没有覆盖equals以实现期望的行为,这时我们就需要覆盖equals方法。
equals方法必须要遵守的通用约定:
- 自反性:对于任何非null的引用值x,x.equals(x)必须返回true;
- 对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true;
- 传递性:对于任何非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方法的诀窍:
- 使用==操作符检查“参数是否为这个对象的引用”;
- 使用instanceof操作符检查“参数是否为正确的类型”;
- 把参数转换成正确的类型;
- 对于该类中的每个“关键域”,检查参数中的域是否与该对象中对应的域相匹配:(1)对于非float也不是double类型的基本类型,可以使用==操作符进行比较(2)对于对象引用域,可以递归调用equals方法(3)对于float域,使用Float.compare方法,对于double域,使用Double.compare方法(4)对于数组域则把以上这些指定原则应用到每个元素上或利用Arrays.equals方法
域的比较顺序可能会影响到equals方法的性能,为了获得最佳的性能,颖最先比较最有可能不一致的域,或者是开销最低的域。
9. 覆盖equals时总要覆盖hashCode
一个很常见的错误根源在于没有覆盖hashCode方法,在每个覆盖了equals方法的类中,也必须覆盖hashCode方法,如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合博阿凯HashMap,HashSet和Hashtable。
约定:
- 在应用程序的执行期间,只要对象的equal方法的比较操作所用到的信息没有被修改,那么对这个同一个对象调用多次,hashCode方法都必须始终如一返回同一个整数。在同一应用程序的多次执行过程中,每次执行所返回的整数可以不一致。
- 如果两个对象根据equals方法比较是相等,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。(相等的对象必须具有相等的散列码)
- 如果两个对象根据equals方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生不同的整数结果,但是给不相等对象产生截然不同的整数结果,有可能提高散列表的性能。
一个号的散列函数通常应该是“为不相等的对此产生不相等的散列码”。散列函数应该把集合中不相等的实例均匀分布到所有可能的散列值上。想要完全达到这种理想的情形是非常困难的,幸运的是,相对接近这种理想情形则并不太困难:
- 把某个非零的常量值,比如说1,保存在一个名为result的int类型的变量中。
- 对于对象中每个关键域f(指equals方法中涉及的每个域),计算int类型的散列码c。
- 按照result = 31 * result + c公式,把散列码c合并到result中。
- 返回result。
其中计算域f的int类型的散列码,有如下的几种场景:
(1)如果该域是boolean类型,则计算(f ? 1 : 0);
(2)如果是byte,char,short或int类型,则计算(int)f;
(3)如果是long,计算(int)(f^f>>>32);
(4)如果是float,则计算Float.flaotToIntBits(f);
(5)如果是double,先计算Double.doubleToLongBits(f)返回long类型,然后按照(3)处理;
(6)如果是对象引用,递归调用对象的hashCode方法;
(7)如果是数组,对每个元素单独处理,或调用Arrays.hashCode方法。
具体可以参考Arrays类里面很多hashCode()方法;
10. 始终要覆盖toString
虽然Object同了toString方法的一个实现,返回的字符串通常并不是类的用户所期望看到的。它包含一个类的名称,以及一个@符号,接着是散列码的无符号16禁止表示法。
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
建议所有的子类都覆盖这个方法。
11. 谨慎地覆盖clone
Cloneable接口的目的是作为对象允许克隆。
既然Cloneable并没有包含任何方法,那么它到底有什么作用呢?它决定了Object中受保护的clone方法实现的行为:如果一个类实现了Cloneable,Object的clone方法就返回该对象的逐域拷贝,否则抛出异常CloneNotSupportedException。

实现接口的版本:

12. 考虑实现Comparable接口
compareTo方法并没有在Object中声明。它是Comparable接口中唯一的方法。
类实现了Comparable接口,就表明它的实例具有内在的排序关系。
违反compareTo约定的类也会破坏其他依赖于比较关系的类。依赖于比较关系的类包括有序集合类TreeSet和TreeMap,以及工具类Collections和Arrays,它们内部包含有搜索和排序算法。
x.参考文档
《Effective Java中文版 第2版》
Effective Java-第三章的更多相关文章
- [Effective Java]第三章 对所有对象都通用的方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 对于所有对象都通用方法的解读(Effective Java 第三章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- 《Effective Java 第三版》新条目介绍
版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...
- EFFECTIVE JAVA 第十一章 系列化
EFFECTIVE JAVA 第十一章 系列化(将一个对象编码成一个字节流) 74.谨慎地实现Serializable接口 *实现Serializable接口付出的代价就是大大降低了“改变这个类 ...
- “全栈2019”Java第三章:安装开发工具IntelliJ IDEA
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Think in Java 第三章操作符
Think in Java 第三章操作符 赋值 对象赋值 我们真正操作的是对对象的引用.所以倘若"将一个对象赋值给另一个对象",实际上是将"引用"从一个地方 ...
- Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——10. 重写equals方法时遵守通用约定
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——14.考虑实现Comparable接口
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——21. 为后代设计接口
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
随机推荐
- Openshift 节点添加和删除
1.节点添加 在新节点上编辑yum源/etc/yum.repo.d/ocp.repo /etc/hosts在主和节点上都加上相应信息 编辑host文件,加入 [OSEv3:children] mast ...
- LaTeX:Figures, Tables, and Equations 插入图表和公式
Figures To insert a figure in a LaTeX document, you write lines like this: \begin{figure} \centering ...
- 使用nsswitch控制linux dns解析顺序
参考:1.DNS原理入门参考:http://www.ruanyifeng.com/blog/2016/06/dns.html 2.http://cn.linux.vbird.org/linux_ser ...
- iOS:极光推送控制器跳转
在前面已经做完了极光消息的推送,那么有消息了,如何跳转到需要的控制器呢?其实,主要还是在userInfo这个消息里面做判断来处理,具体如下: 下面这两个是远程推送时接收消息的方法,这是应用程序提供的方 ...
- Vue侦听器watch
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器.这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化.当需要在数据变化时执行异步或开销较大的操作时,这 ...
- 【甘道夫】Win7环境下Eclipse连接Hadoop2.2.0
准备: 确保hadoop2.2.0集群正常执行 1.eclipse中建立javaproject,导入hadoop2.2.0相关jar包 2.在src根文件夹下拷入log4j.properties,通过 ...
- ModelAndView command
new ModelAndView("student", "command", new Student()); 对“如果在JSP中使用<form:form& ...
- JMeter 十六:加密处理
假设采用MD5进行加密 JMeter 内置的没有MD5加密方法.网上有说采用__MD5函数的,但是我在 Jmeter 2.13 以及 Jmeter 3.2 版本上都没有找到这个函数,官方文档也没有看到 ...
- 初识 Swift编程语言(中文版)
前言 今天Apple公布了新的编程语言Swift.也提供了一本将近400页的 The Swift Programming Language(Swift编程语言). 尽管我没有开发人员账号.没法实际上机 ...
- 基于SpringBoot的Environment源码理解实现分散配置
前提 org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性.Envi ...