栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

equals方法设计思想

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

equals方法设计思想

一、介绍

equals方法用于检测一个对象是否等于另一个对象。它与 == 的区别在于:== 对于对象而言,比较的是两个对象的地址是否相同,而 equals 比较的是两个对象的值是否一致。例如:

String a = "abc";
String b = "abc";
String c = new String("abc");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(b));
System.out.println(a.equals(c));

//输出结果:
//true
//false
//true
//true

从上可以看出,对上而言,== 仅对于对象的地址进行了比较,而不比较对象的值是否相等;equals方法比较了对象的值是否相同,若值相同,则返回 true。

== 对于基本数据类型,比较的是两个数据的值是否相同;对于引用类型而言,比较的是两个引用的地址是否相等。

二、equals方法设计思想

Java语言规范要求equals方法具有下面的特性:

  1. 自反性:对于任何非空引用x, x.equals(x)应该返回true;
  2. 对称性:对于任何非空引用x和y, 当且仅当y.equals(x)返回true时,x.equals(y)返回true;
  3. 传递性:对于任何引用x、y和z, 如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true;
  4. 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果。
  5. 对于任何非空引用x, x.equals(null)应该返回false

我们有这么一个合理的默认行为:如果两个对象引用相等,这两个对象肯定就相等。对于很多类来说,这已经足够了,例如,比较两个PrintStream对象是否相等并没有多大意义。不过,经常需要基于状态检测对象的相等性,如果两个对象有相同的状态,才认为这两个对象是相等的。这时,就需要通过equals方法进行判断。设计方法如下:

Class People {
    String name;
    int age;
}

public boolean equals(Object otherObject) {
    // 如果两个对象引用相等,这两个对象肯定就相等
    if (this == otherObject) {
        return true;
    }
    // 如果otherObject为空,则必须返回false
    if (otherObject == null) {
        return false;
    }
    // 如果两个对象的类不一致,则它们不相等
    if (getClass() != otherObject.getClass()){
        return false;
    }
    People other = (People) otherObject;
    // 判断两个对象的字段是否相等
    return Object.equals(name, other.name)
      && age == other.age;
}

需要注意的是,在return语句中,若使用name.equals(other.name),当name为空时,就会抛出异常,从而导致无法进行判断。

补充

对于上述equals方法设计,我们通过getClass()方法判断两个对象是否属于同一个类,如果显示参数和隐式参数不属于同一个类,而这两个类又具有相同语义的字段,我们仅需要对这一部分进行判断,equals方法又该如何实现呢?或许我们会想到 instanceof进行检测。例如:

Class Student extends People {
    int score; // 分数
}
public boolean equals(Object otherObject) {
    ...
    if (!(otherObject instanceof People)) {
        return false;
    }
    ...
}

此时,p.equals(s),这里的p是一个People对象,s是一个Student对象,并且两个对象都有相同的姓名和年龄。如果再People.equals中用instanceof进行检测,这个调用将返回true。然而此时意味着反过来调用:s.equals§也需要返回true。对称性规则不允许这个方法调用返回false或者抛出异常。
这样就使得Student类收到了束缚。这个类的equals方法必须愿意将自己与任何一个People对象进行比较,而不考虑Student特有的那部分信息。一下子似乎觉得instanceof也不是那么好。

设计建议
  1. 显示参数命名为otherObject, 稍后需要将它强制转换成另一个名为other的变量。
  2. 检测this与otherObject是否相等:if (this == otherObject) return true;
    这条语句只是一个优化。实际上,这是一种经常采用的形式。因为检查身份要比逐个比较字段开销小。
  3. 检测otherObject是否为null,如果为null,返回false。这项检测是很有必要的。
    if (otherObject == null) return false;
  4. 比较this与otherObject的类。如果equals的语义可以在子类中改变,就使用getClass()检测:
    if (getCLass() != otherObject.getClass()) return false;
    如果所有的子类都有相同的相等性语义,可以使用instanceof检测:
    if (!(otherObject instanceof ClassName)) return false;
  5. 将otherObject强制转换为相应类类型的变量:
    ClassName other = (ClassName) otherObject
  6. 现在根据相等性概念的要求来比较字段。使用==比较基本类型字段,使用Object.equals比较对象字段。如果所有的字段都匹配,就返回true;否则返回false。
    return field1 == other.field1 && Object.equals(field2, other field2) && …;
    如果再子类中重新定义equals,就要在其中包含一个super.equals(other)调用。
参考文献

[1] Java 核心技术 卷Ⅰ

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/935942.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号