1 重写equals方法时请遵守通用约定

(1)无需覆盖equals方法的情况

  • 要求独一无二
  • 不要求逻辑相等
  • 超类已经覆盖equals方法,对其子类也适用
  • 一个类是私有的或者是包私有(可以重写后抛出异常,防止被重写)

(2)重写equals方法要保持等价关系

  • 自反性:对于任意非空引用值x,x.equals(x)必须返回true。
  • 对称性:对于任意非空引用值x和y,x.equals(y)必须返回true,当且仅当y.equals(x)返回true。
  • 传递性:对于任意非空引用值x,y,z,如果x.equals(y)返回true而且y.equals(z)也返回true,那么x.equals(z)必须返回true。
  • 一致性:对于任意非空引用值x和y,只要equals方法中使用的信息没有被修改,那么不管多少次调用x.equals(y)都必须一致性地返回true或者false。
  • 对于任意非空引用值x,x.equals(null)必须返回false。

注:重写equals方法需要打破等价关系是不被允许的。

2 重写equals方法都要重写hashCode方法

(1)equals与hashCode的关系

  • equals相等,hashCode必须相等。
  • equals不等,hashCode可以相等,也可以不等。
  • hashCode不等,equals一定不等。

(2)重写原则

  • 不要为了提高性能而试图在哈希码的计算过程中将重要的属性排除掉:防止大量hash冲突
  • 不要为hashCode返回的值提供详细的规范:为了未来拓展

3 始终重写toString方法

(1)重写原则

  • toString方法应该返回类里面所有有用的信息
  • 无论我们是否决定要指明格式,我们都应该清晰地在文档中表达我们的意图

(2)DEMO

  • 指定格式:程序员自行补充注释和格式
/**
* Returns the string representation of this phone number.
* The string consists of twelve characters whose format is
* "XXX-YYY-ZZZZ", where XXX is the area code, YYY is the
* prefix, and ZZZZ is the line number. Each of the capital
* letters represents a single decimal digit. *
* If any of the three parts of this phone number is too small
* to fill up its field, the field is padded with leading zeros.
* For example, if the value of the line number is 123, the last
* four characters of the string representation will be "0123".
*/
@Override
public String toString() {
return String.format("%03d-%03d-%04d",areaCode, prefix, lineNum);
}
  • 不指定格式:通过IDE或者Google AutoValue来自动生成

4 谨慎重写clone方法

(1)重写clone方法

  • 子类需要继承Cloneable接口,否则调用Object的clone方法将抛出CloneNotSupportedException。
  • 如果一个类实现了Cloneable接口,Object的clone方法将返回一个属性逐一拷贝的对象,否则它就抛出一个CloneNotSupportedException异常。
  • 一个类含有引用属性,需要进行深度克隆
public class Stack implement Cloneable{
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
this.elements = new Object[DEFAULT_INITIAL_CAPACITY];
} public void push(Object e) {
ensureCapacity();
elements[size++] = e;
} public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null;
} private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
} @Override
public Stack clone() {
try {
Stack result = (Stack) super.clone();
result.elements = elements.clone(); // 引用属性进行深度克隆
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}

5 考虑实现Comparable或使用Comparator

  • 一个对象在与指定的对象比较顺序时,当该对象小于,等于或者大于指定的对象时,相应地返回一个负的整型值,0或者正的整型值。
  • 若指定对象的类型不能与发起比较的对象进行比较,则抛出ClassCastException异常。
  • 具有自反性,对称性和传递性。
  • 强烈建议(x.compareTo(y) == 0) == (x.equals(y))成立(非绝对,比如:BigDecimal类)
  • compareTo方法中的基本数据类型比较,避免使用+ - > < 运算符,应该使用包装类的比较方法,如:Double.compare。(+ - 可能导致溢出)
  • Comparator示例:
private static final Comparator<PhoneNumber> COMPARATOR =
comparingInt((PhoneNumber pn) -> pn.areaCode)
.thenComparingInt(pn -> pn.prefix)
.thenComparingInt(pn -> pn.lineNum); public int compareTo(PhoneNumber pn) {
return COMPARATOR.compare(this, pn);
}

Effective Java 读书笔记(二):对象通用方法的更多相关文章

  1. Java 读书笔记 (二) 对象和类

    Java 作为一种面向对象语言,支持以下基本概念: 多态 继承 封闭 抽象 类 对象 实例 方法 重载 对象: 是类的一个实例,有状态和行为.以人为例,黄种人.白种人.黑种人为类,每一个具体的人为类的 ...

  2. 《Effective Java》读书笔记二(通用方法)

    No8 覆盖equals方法时请遵守通用约定 通用约定,下面的约定前提都是x/y/z不为null值. 自反性(reflexive),x.equals(x)必须返回true. 对称性(symmetric ...

  3. [Effective Java 读书笔记] 第7章 方法

    第39条 必要时进行保护性拷贝 对于可变类,如果作为参数传入到自己的类里,并作为自己类的数据使用存储时,需要进行保护性拷贝,比如Date是可变的,如果传入一个Date类,最好做一个保护性拷贝,以免在调 ...

  4. 《Effective Java》笔记45-56:通用程序设计

    将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性. 要使用局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方才声明,不要过早的声明. 局部变量的作用域从它被声明的 ...

  5. Effective Java读书笔记——第三章 对于全部对象都通用的方法

    第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定 ...

  6. Effective Java 读书笔记(一):使用静态工厂方法代替构造器

    这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...

  7. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  8. java读书笔记二

    这是我的一些读书笔记: 我研究了一下面向对象: 面向对象符合人类看待事物的一般规律,对象的方法的实现细节是包装的,只有对象方法的实现者了解细节 我觉得面向过程是由过程.步骤.函数组成,过程是核心,面向 ...

  9. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  10. Effective java 读书笔记(2)

    第四条:通过私有构造器强化不可实例化的能力 有时可能需要编写只包含静态方法和静态域的类,这样的工具类不希望被实例化,因为实例化对它来说没有意义. 然而,在缺少显式构造器的情况下,系统会自动提供一个缺省 ...

随机推荐

  1. http-proxy-middleware及express实现反向代理

    $ npm install --save-dev http-proxy-middleware npm install express // 引用依赖 var express = require('ex ...

  2. OVS+VXLAN实现两个宿主机上的VM间的通信

    一.组网图 说明: 1.使用网络命名空间表示vm1和vm2. 因为我没有两台物理服务器. 2.使用virtualbox 的两条虚机模拟作为host1和host2. 二.配置指导 1.创建网桥 br0 ...

  3. Qt编写自定义控件41-自定义环形图

    一.前言 自定义环形图控件类似于自定义饼状图控件,也是提供一个饼图区域展示占比,其实核心都是根据自动计算到的百分比绘制饼图区域.当前环形图控件模仿的是echart中的环形图控件,提供双层环形图,有一层 ...

  4. 三个线程abc顺序执行

    1.使用synchronized悲观锁(秋招阿里的一个笔试题,应该写的比较复杂,然后就没有然后了o(╥﹏╥)o) public class ThreadThreadp { private int fl ...

  5. CDS视图篇 2

    核心数据服务 (CDS) 公司希望使用 SAPS/4HANA 核心数据服务 (CDS) 视图技术.需要学习 CDS 视 图的概念和结构以及语法 . ● 核心数据服务是用于业务实体的 SAP 战略建模方 ...

  6. rhel7免密登录问题

    以前在做linux免密登录时只要执行:cat id_rsa.pub>> authorized_keys,就可以了 后来升级到rhel7之后不行,发现有两个需要改动: 1.修改ssh的配置文 ...

  7. 过滤emoji表情的方法

    public static function replaceEmoji($str) { $str = preg_replace_callback( '/./u', function (array $m ...

  8. talking data 集成

    talking data 集成需要手动添加libz.td

  9. IBM.WMQ订阅消息

    网上关于IBM这个消息队列中间件的资料相对比较少,C#相关的资料就更少了,最近因为要对接这个队列中间件,花了不少功夫去搜索.整理各种资料,遇到很多问题,因此记录下来. 1.基于 amqmdnet.dl ...

  10. 迷惑性很强的crontab

      提到定时任务,我们通常会想起linux的crontab,可以说服务器端大部分定时任务都是由它完成的.这东西固然耗用,但是坑也不少.   这不,昨天我在部署一个备份任务的时候,就不幸踩坑了.差点酿成 ...