1、覆盖equals请遵守通用规定。
不需要覆写equals的场景:
a.类的每个实例都是唯一的。
b.类不需要提供“逻辑相等”的测试功能。
c.超类已经覆盖了equals的方法。
d.类是私有,or包私有,保证equals方法用不被调用。
覆写场景:有独特的“逻辑相等”。
实现要求:
a.自反,对称,传递,一致(多次比较得一样),对于任何非null值和null比较必须返回false。
一致:不要使equals依赖不可靠的资源。(比如java.net.URL的equals依赖于URL中IP的的比较,IP可能会变。)
对于float,double可以使用Float和Double的compare(float,float),compare(double,double)方法做比较。因为有Float.NaN,-0.0f等。虽然可以用Float.equals(),Double.equals()的静态方法对double和float进行比较,但是自动装箱,导致性能下降。
注意考虑性能:把关键的先决条件放前面比较,比如只要面积不相等,就不需要再比较顶点和角。
b.覆盖equals总是要覆盖hashCode
c.不要试图让equals过于智能。
d.不要将equals声明中的Object对象替换为其他类型。反例:equals(MyClass o);正例:equals(Object o)
2、覆盖equals总要覆盖hashCode
equals相等,hashCode一定要相等。如果equals不相等,hashCode最好不相等。
实现hashCode的方法:
第一个域的hashCode就是本身的hashCode(一般是Type.hashCode(f))
每个域hashCode*31 + 累计的域的hashCode
使用31是因为31是奇素数。如果使用偶数,乘法溢出会导致信息丢失,乘以2等价于移位运算。信息丢失,hash碰撞概率更大。乘的数不宜过大,不宜过小。否则容易碰撞。31应该是个不易碰撞的因子。31有个好特性,可以用移位和减法代替。31*i=(32-1)*i=(32i -i)=(i<<5)-i。
其他hashCode方法:Arrays.hashCode()对数组每个元素hashCode的总的组合。
尽可能不冲突:com.google.common.hash.Hashing[Guava].
不注重性能可以用法Object.hash(Object... o)
不可变类,并且hashCode计算开销大,可以考虑缓存,或者延迟加载。
private int hashCode;
@Override public int hashCode(){
int result = hashCode;
if(result == 0){
//再计算hashCode;
}
return result;
}
不要试图从hashCode计算中排除掉关键领域提高性能,可能会导致hash碰撞更严重。
3、始终要覆盖toString方法
默认toString:类名+@+hashCode无符号16进制整数。
4、谨慎地覆盖clone
Object的clone方法是受保护的(protected),不能直接调用,得由子类去调用,实现Cloneable方法,否则报CloneNotSupportedException。
不可变类永远不要提供克隆办法,因为它只会激发不必要的克隆。
如果对象中包含的域引用了可变的对象(Object的clone方法只会做引用复制),比如数组,对克隆对象的数组改变,会影响原来的对象!!!(深拷贝和浅拷贝的问题)
实际上,clone方法就是另外一个构造器;必须确保它不会伤害到原始的对象,并确保正确地创建被克隆对象的约束条件。
在数组上调用clone返回的数组,其编译时的类型与被克隆数组的类型相同。这是复制数组的最佳习惯。数组是clone方法唯一吸引人的地方。
就像序列化一样,Clonable架构与引用可变对象的final域的正常用法是不相兼容的。
克隆复杂对象最后一种办法是:
先调用super.clone(),然后哉把结果对象中的所有域都设置成初始状态。
公有的clone方法应该省略throws声明,因为不抛出受检异常的方法使用起来更轻松。
为继承而设计的类最好自己实现一个protected的clone方法,里面抛出ClassNotSupportedException
同时有必要的时候,在多线程环境要考虑clone方法线程安全。
对象拷贝的更好办法是提供一个拷贝构造器或者是拷贝工厂。
public Yum(Yum yum){};
public static Yum newInstance(Yum yum){};
最好的办法就是不应该扩展clone这个接口。少数有必要才实现。当然基本类型/不可变类型数组clone是例外。
5、考虑实现Comparable接口
实现Comparable要求:
sgn表示根据表达式的值返回-1,0,1
1、sgn(x.compareTo(y)) = -sgn(y.compareTo(x))
2、传递性
3、如果x.compareTo(y) = 0,则 sgn(x.compareTo(z)) = sgn(y.compareTo(z))
4、最好保证(x.compareTo(y) == 0)= (x.equals(y)),否则最好注释说明
只在同类型之间比较,在不同类型之间就抛出ClassCastException
违反compareTo的约定也会破坏依赖的相关类,比如TreeSet,TreeMap,以及工具类Collections和Arrays。
Collection、Set、Map的通用约定是用equals来做等同性,但是有序集合使用compareTo而不是equals来做等同性。比如HashSet添加new BigDecimal("1.0") 和 new BigDecimal("1.00")是2个元素,
TreeSet是1个元素。
先比较重要字域,再比较次要的。
java 8 开始 Comparator配置了一组比较器构造方法:long,int,double,float等Comparable.comparingInt();
实现compare 不要用+,-之类可能导致整数溢出的情况。避免使用<,>大于小于实现很复杂。多用相关装箱类型中的compare方法,或者Comparator的比较构造器。

Effective Java读书笔记--对所有对象都通用的方法的更多相关文章

  1. Effective Java 学习笔记之所有对象都通用的方法

    一.覆盖equals时请遵守通用约定 1.满足下列任何一个条件时,不需要覆盖equals方法 a.类的每个实例本质上都是唯一的.此时就是Object中equals方法所表达的含义. b.不关心类是否提 ...

  2. Effective Java2读书笔记-对于所有对象都通用的方法(一)

    第8条:覆盖equals时请遵守通用约定 ①约定的内容 自反性.对于任何非null的引用值x.x.equals(x)必须返回true. 对称性.对于任何非null的引用值x和y.当且仅当y.equal ...

  3. Effective Java2读书笔记-对于所有对象都通用的方法(二)

    第10条:始终要覆盖toString 这一条没什么好讲的,就是说默认的toString方法打印出来的是类名+@+十六进制哈希码的值.我们应该覆盖它,使它能够展示出一些更为详细清晰的信息,这个看实际情况 ...

  4. Effective Java2读书笔记-对于所有对象都通用的方法(三)

    第12条:考虑实现Comparable接口 这一条非常简单.就是说,如果类实现了Comparable接口,覆盖comparaTo方法. 就可以使用Arrays.sort(a)对数组a进行排序. 它与e ...

  5. [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条

    这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法 第八条 覆盖equals时需要遵守的约定 Object中的equals实现,就是直接对 ...

  6. Effective Java:对于全部对象都通用的方法

    前言: 读这本书第1条规则的时候就感觉到这是一本非常好的书.可以把我们的Java功底提升一个档次,我还是比較推荐的.这里我主要就关于覆盖equals.hashCode和toString方法来做一个笔记 ...

  7. [Effective Java]第三章 对所有对象都通用的方法

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. Effective Java 读书笔记

    创建和销毁对象 >考虑用静态工厂方法替代构造器. 优点: ●优势在于有名称. ●不必再每次调用他们的时候都创建一个新的对象. ●可以返回原返回类型的任何子类型的对象. ●在创建参数化类型实例的时 ...

  9. Java高效编程之二【对所有对象都通用的方法】

    对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...

随机推荐

  1. idea或者java远程提交spark任务到yarn,Exception1

    spark通過idea远程提交job到yarn: Caused by: java.lang.ClassCastException: cannot assign instance of scala.co ...

  2. sparkStreaming实时数据处理的优化方面

    1.并行度 在direct方式下,sparkStreaming的task数量是等于kafka的分区数,kakfa单个分区的一般吞吐量为10M/s 常规设计下:kafka的分区数一般为broken节点的 ...

  3. Head First 设计模式 —— 03. 装饰器 (Decorator) 模式

    思考题 有如下类设计: 如果牛奶的价钱上扬,怎么办?新增一种焦糖调料风味时,怎么办? 造成这种维护上的困难,违反了我们之前提过的哪种设计原则? P82 取出并封装变化的部分,让其他部分不收影响 多用组 ...

  4. shell脚本学习之6小时搞定(6)-重定向及其他

    shell学习之-重定向及其他 目录 shell学习之-重定向及其他 1.输出重定向 2.输入重定向 3.重定向深入讲解 4./dev/null 文件 5.awk Unix 命令默认从标准输入设备(s ...

  5. NOIP初赛篇——09原码、反码和补码

    一.数的原码.补码和反码表示 机器数和真值 ​ 在计算机中,表示数值的数字符号只有0和1两个数码,我们规定最高位为符号位,并用0表示正符号,用1表示负符号.这样,机器中的数值和符号全"数码化 ...

  6. 醒醒!Python已经支持中文变量名啦!

    最近,我在翻阅两本比较新的 Python 书籍时,发现它们都犯了一个严重的低级错误! 这两本书分别是<Python编程:从入门到实践>和<父与子的编程之旅>,它们都是畅销书,都 ...

  7. Python requirements.txt 语法

    前言 之前一直苦于一个问题,比如一些包在Win上安装不了,比如 uvloop 但是为了提高效率,代码中必须有这个模块 在运行中可以通过 os 模块判断是否使用, 那依赖文件呢? requirement ...

  8. win安装python模块出现依赖问题的解决方法 & No module named 'MySqldb'

    前言 一年多了,还在写这种问题,羞愧. 新公司不让用自己的电脑,配的winPC,项目启不起来,之前也出现过这个问题,是py3缺少某个模块,但是自己没记,这次记一下好了. No module named ...

  9. Openstack Keystone 认证服务(四)

    Openstack Keystone 认证服务(四) keystone 的安装完全依赖ocata的源, 如果没有建议自己搭建. 否则用的源不对会产生各种奇葩问题. 创建keystone库和用户: ## ...

  10. 有了链路日志增强,排查Bug小意思啦!

    在工作中,相信大家最怕的一件事就是听到有人在工作群艾特你:某某功能报错啦... 然后你就得屁颠屁颠的去服务器看日志,日志量少还好点,多的话找起来太麻烦了.不太容易直接定位到关键地方. 东找找西找找,好 ...