Effective Java 读书笔记(二):对于所有对象都通用的方法
来源:互联网 发布:sql去重 编辑:程序博客网 时间:2024/06/05 08:36
- Effective Java 读书笔记二对于所有对象都通用的方法
- 覆盖 equals 时要遵守的约定
- 覆盖 equals 的时候总是覆盖 hashCode
- 始终要覆盖 toString
- 谨慎覆盖 clone
- 考虑实现 Comparable 接口
Effective Java 读书笔记(二):对于所有对象都通用的方法
尽管 Object 是一个具体的类,但设计它主要是为了扩展,它的所有非 final 方法(equals、hashCode、toString、clone)都有明确的通用约定。任何一个类,在覆盖这些方法的时候都要遵守通用约定。如果违反约定,其他依赖这些约定的类(比如 HashMap、HashSet)就无法结合该类一起正常工作。
覆盖 equals 时要遵守的约定
有一些情况,是不需要覆盖的:
1. 如果不覆盖 equals,那么类的每个实例都是唯一的。对于代表活动实体而非值的类来说就是如此,比如 Thread。
2. 不关心类是否提供“逻辑相等”的测试功能。
3. 超类提供了 equals,子类从超类继承过来的行为对子类是合适的。
4. 类是私有的或包级私有的,可以确定它的 equals 方法不会被调用。这种应该可以覆盖 equals 方法,以防被意外调用:
public boolean equals(Object obj) { throw new RuntimeException("equals not support");}
那么什么时候应该覆盖 equals 呢?类有自己的“逻辑相等”的概念,而且超类 equals 方法不满足条件,这通常就是值类,比如 Integer、Date。覆盖 equals 时必须遵循一些通用约定:
1. 自反性
2. 对称性
3. 传递性
4. 一致性
实现 equals 方法时的一些诀窍:
1. 先判 null,null 则返回 false。
2. 使用 == 检查是否为同一个对象的引用,是则返回 true。
3. 使用 instanceof 检查是否为正确的类型,否则 false。
剩下的就是对比每个关键域了。
覆盖 equals 的时候总是覆盖 hashCode
如果覆盖了 equals 但是没有覆盖 hashCode,就会违反通用约定,从而导致该类无法结合所有基于散列的集合一起正常工作,这样的集合包含 HashMap、HashSet等。约定如下:
1. 只要 equals 方法比较所需要的信息没有修改,那么 hashCode 方法的返回值也不能变。
2. 两个对象根据 equals 判定为相等,那么其 hashCode 也必须相等。
3. 两个对象根据 equals 判定为不相等,hashCode 可以不同,也可以相同。不同的话,能够提高散列表的性能。
始终要覆盖 toString
主要用于打日志调试,如果对性能要求不高,可以直接输出 Json 串。
谨慎覆盖 clone
所有实现了 Cloneable 接口的类,都应该用一个公有方法覆盖 clone。此方法要首先调用 super.clone() ,如果就此结束,那就只是“浅拷贝”了。如果需要“深拷贝”,则需要手动拷贝任何包含内部“深层结构”的可变对象。下面我们给一个示例:
public class Pojo implements Cloneable { private String str; private List<Integer> intList; private int i; @Override public Pojo clone() throws CloneNotSupportedException { return (Pojo)super.clone(); }}
在 JDK1.5 中引入了协变返回类型作为泛型,覆盖方法的返回类型可以是被覆盖方法的子类了。由于 Object 的 clone 方法返回的是 Object,所以 Pojo 的 clone 方法内部进行了显式类型转换。这体现了一个原则:永远不要让客户去做任何类库能够替客户完成的事情。上面这个示例依然是浅拷贝的,因为 intList 是一个可变对象,默认情况拷贝的只是其引用。其深拷贝版本如下:
public class Pojo implements Cloneable { private String str; private List<Integer> intList; private int i; @Override public Pojo clone() throws CloneNotSupportedException { Pojo clone = (Pojo) super.clone(); List<Integer> dstList = new ArrayList<>(intList); clone.setIntList(dstList); return clone; } public void setIntList(List<Integer> intList) { this.intList = intList; }}
这里 List 中元素是 Integer 类型,Integer 是不可变的,否则还需要额外对每个元素做一次拷贝。
还有一个问题:clone 架构与引用可变架构的 final 域正常用法不相兼容。比如,上面的 intList 如果声明为 final,是没办法做深度拷贝的。
在实际项目中,推荐使用拷贝构造方法或静态工厂来代替 clone,因为这样更灵活,也没有 clone 的那些约束,不与 final 冲突。
考虑实现 Comparable 接口
如果一个值类具有明显的内在排序关系,你就应该考虑实现 Comparable 接口:
public interface Comparable<T> { public int compareTo(T o);}
一旦实现了 Comparable 接口,就可以跟很多泛型算法以及依赖于该接口的集合实现进行协作,比如:
Arrays.sort(a);
compareTo 方法要遵守的通用约定和 equals 方法类似。对于 Collection、Map 或 Set 的通用约定是按照 equals 来定义的,而有序集合 TreeMap、TreeSet 是按照 Comparable 来定义的。所以应该尽量保证两个对象 equals 返回 true 时,compateTo 返回 0,否则有序集合就无法遵守集合接口的通用约定了。
- 《Effective Java》读书笔记(二)之对于所有对象都通用的方法
- 【effective Java读书笔记】对于所有对象都通用的方法(二)
- Effective Java 读书笔记(二):对于所有对象都通用的方法
- Effective Java读书笔记(第3章-对于所有对象都通用的方法)
- 【读书笔记】《Effective Java》(2)--对于所有对象都通用的方法
- 【effective Java读书笔记】对于所有对象都通用的方法(一)
- 【effective Java读书笔记】对于所有对象都通用的方法(三)
- Effective Java(二) 对于所有对象都通用的方法
- Effective Java学习笔记(二)对于所有对象都通用的方法
- Effective Java读书笔记(3对于所有对象都通用的方法)
- effective java-读书笔记-第三章 对于所有对象都通用的方法
- Effective Java读书笔记——第三章 对于所有对象都通用的方法
- effective java 读书笔记---第三章对于所有对象都通用的方法
- Effective Java:对于所有的对象都通用的方法
- effective java(对于所有对象都通用的方法)
- Effective Java:对于所有对象都通用的方法
- Effective Java Note(对于所有对象都通用的方法)
- Effective Java:对于所有对象都通用的方法
- 截取图片生成头像插件
- code::blocks打开替换
- Qt 之 QButtonGroup Class
- Spring Boot:定制servlet filters
- 使用yum命令报错File "/usr/bin/yum", line 30 except KeyboardInterrupt, e:
- Effective Java 读书笔记(二):对于所有对象都通用的方法
- 关于 tomcat 集群中 session 共享的三种方法
- eclipse:A child container failed during start
- 无法对Image Service启用Java版SOE功能
- 封装ajax和Promise
- 相机对焦和调焦距的区别是什么 ?
- 【软考】课本--章节整理
- python(二)mac环境(macOS10.12.6)下的python3.6使用mysql
- PHP上传图片并缩放