• equals 方法示例
// 代码来自《Java核心技术 卷I》P167
// 父类
public class Employee{
...
public boolean equals(Object otherObject){
// a quick test to see if the objects are identical
if(this == otherObject) return true; // must return false if the explicit parameter is null
if(otherObject == null) return false; // if the classes don't match, they can't be equal
// 笔者注:子类通过super.equals方法调用到此处时,getClass()的结果是子类
if(getClass() != otherObject.getClass())
return false; // now we know otherObject is a non-null Employee
Employee other = (Employee) otherObject; // test whether the fields hava identicial values
// 笔者注:此处使用Objects.equals方法是为了防备name或hireDay可能为null的情况
return Objects.equals(name, other.name)
&& salary == other.salary
&& Objects.equals(hireDate, other.hireDate);
}
}
// 子类
// 先调用超类的equals,如果返回false,对象则不可能相等
// 如果父类中的域都相等,再比较子类的实例域
public class Manager extends Employee{
...
public boolean equals(Object otherObject){
if(!super.equals(otherObject)) return false;
// super.equals checked that this and otherObject belong to the same class
Manager other = (Manager) otherObject;
return bonus == other.bonus;
}
}
  • Java 语言规范要求 equals 方法具有以下特性:

    • 自反性:x.equals(x) 应当返回 true
    • 对称性:x.equals(y) 与 y.equals(x) 返回应当相同
    • 传递性:如果 x.equals(y) 返回 true,且 y.equals(z) 也返回 true,则 x.equals(z) 也应返回 true
    • 一致性:如果 x 与 y 引用的对象没有发生变化,则 x.eqauls(y) 也不应变化
    • 对于任意的非空引用 x,x.equals(null) 应当返回 false
  • 在上面的例子中,如果发现类型不一致,就返回 false。但同时也有许多程序员喜欢采用以下代码进行检测 if(!(otherObject instanceof Employee)) return false; 但这样没有解决 otherObject 是子类的情况(父类对象.eqaules(子类对象))下的比较问题。

  • 关于 getClass 与 instanceof 两种检测方法:

    • 如果子类能够拥有自己的相等概念,则对称性需求将强制采用 getClass 进行检测。
    • 如果由超类决定相等的概念,那么就可以使用 instanceof 进行检测,这样可以在不同子类的对象之间进行相等的比较。
  • 编写完美的 equals 方法的建议:

    1. 显式参数命名为 otherObject,稍后需要将它转换为另一个叫做 other 的变量。
    2. 检测 this 与 otherObject 是否引用同一个对象:return this == otherObject;
    3. 检测 otherObject 是否为 null,是则返回 false。
    4. 比较 this 与 otherObject 是否属于同一个类:
      • 如果 equals 的语义在每个子类中有所改变,就使用 getClass 检测:return getClass() != otherObject.getClass();
      • 如果所有的子类都拥有统一的语义,就使用 instanceof 检测:return (!(otherObject instanceof ClassName));
    5. 将 otherObject 转换为相应的类类型变量:ClassName other = (ClassName) otherObject
    6. 对所有需要比较的域进行比较。使用 == 比较基本类型域,使用 equals 比较对象域。如果所有的域都匹配,则返回 true,否则返回false。
      return field1 == other.field1
      && Objects.equals(field2, other.field2)
      && ...;

      如果在子类中重新定义 equals,就要在其中包含调用 super.equals(other)。

「JavaSE 重新出发」05.01.01 equals 方法的更多相关文章

  1. 「JavaSE 重新出发」05.03.01 利用反射分析类

    在 java.lang.reflect 包中有三个类 Field, Method 和 Constructor 分别用于描述类的域.方法和构造器. Class 类中的 getFields, getMet ...

  2. 「JavaSE 重新出发」05.01.02 hashCode 方法、toString 方法

    hashCode 方法 散列码(hash code)是由对象导出的一个整形值(可以是负数).其是没有规律的,如果x与y是两个不同的对象,则x.hashCode()与y.hashCode()基本上不会相 ...

  3. 「JavaSE 重新出发」05.01 继承

    继承 一个对象变量可以指示多种实际类型的现象被称为多态(polymorphism). 在运行时能够自动地选择调用哪个方法的现象称为动态绑定(dynamic binding). 如果是private方法 ...

  4. 「JavaSE 重新出发」05.02 泛型数组列表、包装类

    泛型数组列表 ArrayList 是一个采用类型参数(type parameter)的泛型类(generic class). java ArrayList<Employee> staff ...

  5. 「JavaSE 重新出发」05.03.03 使用反射编写泛型数组代码

    Employee[] a = new Employee[100]; // ... // array is full a = Arrays.copyOf(a, 2 * a.length); 如何编写这样 ...

  6. 「JavaSE 重新出发」05.03.02 在运行时使用反射分析对象

    在编写程序时,如果知道想要查看的域名和类型,查看指定的域是一个很容易的事,而利用反射机制可以查看在编译时还不清楚的对象域. java Employee tank = new Employee(&quo ...

  7. 「JavaSE 重新出发」05.03 反射

    能够分析类能力的程序称为反射(reflection). 反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵 Java 代码的程序. 反射机制可以用 ...

  8. 「JavaSE 重新出发」02.01 基本数据类型

    基本数据类型 1. 整型 注意:Java 没有任何无符号(unsigned)形式的 int.long.short 或 byte 类型. 不同进制的表示形式: 十六进制数值有一个前缀0x或0X(如0xC ...

  9. 「JavaSE 重新出发」01. Java介绍

    「白皮书」关键术语 简单性(C++--) 面向对象 分布式 健壮性 安全性 体系结构中立 可移植性 解释型 高性能 多线程 动态性 Java 发展历程 SUN公司--Stanford Universi ...

随机推荐

  1. hibernate简单集合映射和获取

    简单集合映射(可以直接获取) // javabean设计 public class User { private int userId; private String userName; // 一个用 ...

  2. linu问题集锦

    问题1 系统卡 慢 执行命令延迟/var/spool/mail下root文件过大导致/var磁盘空间92% cd / && du | sort -n | tail -n 10 查看排名 ...

  3. Python爬虫1-----urllib模块

    1.加载urllib模块的request from urllib import request 2.相关函数: (1)urlopen函数:读取网页 webpage=request.urlopen(ur ...

  4. javascript的带操作符的赋值运算

    看犀牛书发现的问题 下面两个表达式 表达式一 data[i++] *= 2; 表达式二 data[i++] = data[i++] * 2;   var data = [7,8,9]; var i = ...

  5. 计蒜客 阿里天池的新任务—简单( KMP水 )

    链接:传送门 思路:KMP模板题,直接生成 S 串,然后匹配一下 P 串在 S 串出现的次数,注意处理嵌套的情况即可,嵌套的情况即 S = "aaaaaa" ,P = " ...

  6. BZOJ 1835 [ZJOI2010]基站选址 (线段树优化DP)

    题目大意:略 洛谷题面传送门 BZOJ题面传送门 注意题目的描述,是村庄在一个范围内去覆盖基站,而不是基站覆盖村庄,别理解错了 定义$f[i][k]$表示只考虑前i个村庄,一共建了$k$个基站,最后一 ...

  7. Strtus配置Tomcat出现问题

    在使用 eclipse 过程中,如果你加入了某些自定义的框架(比如 struts)后,在启动 services 后, 控制台出现一片红色的字样,表明有问题.这时仔细查看 eclipse 控制台信息, ...

  8. APS.NET webform中的isPostBack

    IsPostBack介绍Page.IsPostBack是一个标志:当前请求是否第一次打开. 调用方法为:Page.IsPostBack或者IsPostBack或者this.IsPostBack或者th ...

  9. 51nod 1413:权势二进制

    1413 权势二进制 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 一个十进制整数被叫做权势二进制,当他的十进制 ...

  10. centos6安装eclipse

    1. 下载eclipse 我下载的是eclipse-jee-juno-SR2-linux-gtk-x86_64.tar.gz 能够在http://www.eclipse.org/downloads/处 ...