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. Beta冲刺——第五天

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE1 这个作业要求在哪里 https://edu.cnblogs.com/campus/fz ...

  2. 项目API接口鉴权流程总结

    权益需求对接中,公司跟第三方公司合作,有时我们可能作为甲方,提供接口给对方,有时我们也作为乙方,调对方接口,这就需要API使用签名方法(Sign)对接口进行鉴权.每一次请求都需要在请求中包含签名信息, ...

  3. Java菜鸟在IP问题踩坑了

    之前有做过获取客户端公网IP的项目 一般都是 正常的request.getRemoteAddr 或者request.getRemoteHost 可获取到客户端的公网IP, 或者项目部署在有nginx代 ...

  4. Goland 设置代码格式化

    前言 之前一直喜欢 VsCode 的代码自动格式化和其他的一些功能 今天了解到原来 Goland 也有这些功能, 想想也对, 毕竟这么大 正文 Goland设置代码格式化 进入设置,按需选择要使用的, ...

  5. Java进阶专题(二十一) 消息中间件架构体系(3)-- Kafka研究

    前言 Kafka 是一款分布式消息发布和订阅系统,具有高性能.高吞吐量的特点而被广泛应用与大数据传输场景.它是由 LinkedIn 公司开发,使用 Scala 语言编写,之后成为 Apache 基金会 ...

  6. LeetCode404.左叶子之和

    题目 法一.广度优先搜索 1 class Solution { 2 public: 3 int sumOfLeftLeaves(TreeNode* root) { 4 if(root == NULL) ...

  7. buuctf刷题之旅—web—EasySQL

    打开环境,发现依旧是sql注入 GitHub上有源码(https://github.com/team-su/SUCTF-2019/tree/master/Web/easy_sql) index.php ...

  8. me21n增强BADI:ME_PROCESS_PO_CUST之process_account

    当实施ME_PROCESS_PO_CUST这个badi来增强ME21N的时候,用了到方法process_account,既对ME21N的行项目的科目分配做增强.主要用到如下类: IF_PURCHASE ...

  9. centos7安装docker、docker-compose、es7.3.0、kibana7.3.0

    一.安装docker 1.更新yum包 sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker docker-common docker- ...

  10. ATtiny3217 x WS2812B梦幻联动

    TinyAVR 1-series是Microchip于2018年推出的AVR单片机系列,定位是新一代的8位单片机,ATtiny3217是其中最高端的一款.相比于ATmega328P那个时代的AVR,A ...