《Effective Java》读书笔记(二)之对于所有对象都通用的方法
第八条 在改写equals的时候请遵守通用约定
一般以下几种情况,不适宜覆盖equals方法 
1.类的每个实例本质上都是唯一的,对于代表活动实体而不是值的类确实如此,例如Thread.
2.不关心类是否提供了“逻辑相等”的测试功能
3.超类已经覆盖了equals,从超类继承过来的行为对子类也是合适的
4.类是私有的或者包级私有的,可以确定它的equals方法永远不会被调用。
那什么情况应该覆盖Object.equals呢?如果类具有自己特有的“逻辑相等”的概念(不同于对象等同的概念),而且超类没有覆盖equals以实现期望的行为,就需要进行覆盖,这通常属于“值类”的情形,例如Integer和Date。当使用equals来比较对象, 是希望他们在逻辑上是否相等, 而不是指向同一对象, 或者用来作为Map的key以及集合Set中的元素时, 就必须复写equals方法.
实例受控,确保“每个值最多只存在一个对象”的类,枚举通常属于这种类型。对于枚举类型来说, 逻辑相等与对象相等是同一回事, 因此不需要覆盖equals方法。
equals的改写规范: 
 1)自反性:对于任何非null的引用值x,x.equals(x)一定为true 
 2)对称性:对于任何非null的引用值x和y,当且仅当x.dquals(y)为true;那么y.equals(x)也必须为true 
 3)传递性:对于任何非null的引用值x和y和z,如果x.equals(y)为true,y.equals(z);那么x.equals(x)也必须为true 
 4)一致性:对于任何非null的引用值x和y,如果用于equals比较的对象信息没有被修改的话,那么多次调用x.dquals(y)返回的值是一致的 
 5)对于非null引用值x,x.equals(null)一定返回false
接下来是逐一解析上面几个原则: 
 2)对称性
public final class CaseInsensitiveString {
    private final String s;
    public CaseInsensitiveString(String s) {
        if (s == null)
            throw new NullPointerException();
        this.s = s;
    }
    // Broken - violates symmetry!
    @Override
    public boolean equals(Object o) {
        if (o instanceof CaseInsensitiveString)
            return s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
        if (o instanceof String) // One-way interoperability!
            return s.equalsIgnoreCase((String) o);
        return false;
    }
    // This version is correct.
    // @Override public boolean equals(Object o) {
    // return o instanceof CaseInsensitiveString &&
    // ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
    // }
    public static void main(String[] args) {
        CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
        String s = "polish";
        System.out.println(cis.equals(s) + "  " + s.equals(cis));
    }
}
上面代码中的equals企图和String进行比较操作,假设我们有一个不区分大小的字符串和一个普通的字符串:
  CaseInsensitiveString cis = new CaseInsensitiveString("Test");
        String s = "test";
此时cis.equals(s)会返回true,CaseInsensitiveString 类中做了兼容大小写的处理,但是String 的equals方法是不知道要不区分大小写1的,所以s.equals(cis)会返回false,违反了自反性
假如你把CaseInsensitiveString 放到一个集合中
List<CaseInsensitiveString> list = new ArrayList<>();
        list.add(cis);
        list.contains(s);
list.contains(s)有可能返回true,也可能是false,甚至会抛出RumtimeException
为了解决这个问题,只要企图与String互操作的这段代码从equals去掉即可
@Override
    public boolean equals(Object o) {
        return o instanceof CaseInsensitiveString&&s.equalsIgnoreCase(((CaseInsensitiveString) o).s);
    }
3)传递性: 
 首先以一个简单不可变的二维整形Point类作为开始
《Effective Java》读书笔记(二)之对于所有对象都通用的方法的更多相关文章
- 《Effective Java》第3章 对于所有对象都通用的方法
		
第8条:覆盖equals时请遵守通用约定 覆盖equals方法看起来似乎很简单,但是有许多覆盖方式会导致错误,并且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每 ...
 - 《Effective Java》第2章 对所有对象都通用的方法
		
第10条:覆盖equals时,请遵守通用约定 1.使用==来比较两个对象的时候,比较的是两个对象在内存中的地址是否相同(两个引用指向的是否为同一个对象):Object中定义的equals方法也是这样比 ...
 - Java高效编程之二【对所有对象都通用的方法】
		
对于所有对象都通用的方法,即Object类的所有非final方法(equals.hashCode.toString.clone和finalize)都有明确的通用约定,都是为了要被改写(override ...
 - Effective Java 读书笔记之一 创建和销毁对象
		
一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...
 - 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
		
类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...
 - [Effective Java 读书笔记] 第三章 对所有对象都通用的方法 第八 ---- 九条
		
这一章主要讲解Object类中的方法, Object类是所有类的父类,所以它的方法也称得上是所有对象都通用的方法 第八条 覆盖equals时需要遵守的约定 Object中的equals实现,就是直接对 ...
 - Effective Java:对于全部对象都通用的方法
		
前言: 读这本书第1条规则的时候就感觉到这是一本非常好的书.可以把我们的Java功底提升一个档次,我还是比較推荐的.这里我主要就关于覆盖equals.hashCode和toString方法来做一个笔记 ...
 - [Effective Java]第三章 对所有对象都通用的方法
		
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
 - Effective java读书笔记
		
2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...
 - Effective Java读书笔记完结啦
		
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
 
随机推荐
- 20145216史婧瑶《Java程序设计》第一周学习总结
			
20145216 <Java程序设计>第1周学习总结 教材学习内容总结 第一章 Java平台概论 1.1 Java不只是语言 1.Java三大平台:Java SE.Java EE与Java ...
 - 20145331 《Java程序设计》第10周学习总结
			
20145331 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置 ...
 - flex 的总结
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - checkbox及css实现点击下拉菜单
			
面试遇到的问题.用checkbox中的:checked伪类选择器实现. 通过label标签来触发checkbox的unchecked 和checked两种状态:用css普通同胞选择器 ~.另外补充一点 ...
 - 索引选择性与cardinality
			
索引选择性 索引选择性是索引基数(cardinality)与表中数据行数(n_row_in_table)的比值,即 索引选择性=索引基数/数据行 其中cardinality是索引中不重复记录的预估值. ...
 - activity之间通过全局变量传递数据
			
activity之间通过全局变量传递数据 一.简介 Application域中的onCreate方法是Android程序的入口,Android程序运行的时候就自动加载Application的对象,感觉 ...
 - Opentsdb简介(一)
			
原文:http://www.jianshu.com/p/0bafd0168647 1.OpenTSDB介绍 1.1.OpenTSDB是什么?主要用途是什么? 官方文档这样描述:OpenTSDB is ...
 - CentOS 7.2下编译安装PHP7.0.10+MySQL5.7.14+Nginx1.10.1
			
一.安装前的准备工作 1.yum update #更新系统 2.yum install gcc gcc-c++ autoconf automake cmake bison m4 libxml2 ...
 - SpringBoot+MyBatis简单数据访问应用
			
因为实习用的是MyBatis框架,所以写一篇关于SpringBoot整合MyBatis框架的总结. 一,Pom文件 <?xml version="1.0" encoding= ...
 - UVALive-3523 Knights of the Round Table (双连通分量+二分图匹配)
			
题目大意:有n个骑士要在圆桌上开会,但是相互憎恶的两个骑士不能相邻,现在已知骑士们之间的憎恶关系,问有几个骑士一定不能参加会议.参会骑士至少有3个且有奇数个. 题目分析:在可以相邻的骑士之间连一条无向 ...