本文共 3366 字,大约阅读时间需要 11 分钟。
-- Start
重写 equals 方法是一件很令人头疼的事情, Java 语言规范要求 equals 方法具有下面的特性:
1. 自反性: x.equals(x)应该返回true.2. 对称性: 如果x.equals(y)返回true, 那么y.equals(x)也应该返回true.3. 传递性: 如果x.equals(y)返回true, y.equals(z)返回true, 那么x.equals(z)也应该返回true.4. 一致性: 如果对象没有变化, 反复调用equals方法应该返回相同的结果.5. x.equals(null) 应该返回false.看上去很简单, 但是在涉及继承的时候, 稍有不慎就违反了对称性, 下面是一个例子.
public class Test { public static void main(String[] args) { Poeple p = new Poeple(); p.setName("ZhangSan"); p.setAge(20); Student s = new Student(); s.setName("ZhangSan"); s.setAge(20); s.setID(1); System.out.println("p.equals(s) == " + p.equals(s)); System.out.println("s.equals(p) == " + s.equals(p)); }}class Poeple { private String name; private int age; @Override public boolean equals(Object otherObject) { if (this == otherObject) return true; if (otherObject == null) return false; if (!(otherObject instanceof Poeple)) return false; Poeple other = (Poeple) otherObject; return name.equals(other.name) && age == other.age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}class Student extends Poeple { private int ID; // 学号 @Override public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; if (!(otherObject instanceof Student)) return false; Student other = (Student) otherObject; return ID == other.ID; } public int getID() { return ID; } public void setID(int iD) { ID = iD; }}结果如下:
p.equals(s) == trues.equals(p) == false出现这种情况的原因是超类与子类有不同的比较规则, 实际的情况有以下两种:
1. 由超类决定是否相等, 如: 不管是学生还是老师, 每个人都有身份证号, 由身份证号来确定两个人是否是同一个人, 下面是一个范例程序.
class Poeple { private int ID; private String name; // 由于超类决定是否相等, 可以将equals方法设置为final, 禁止子类重写 @Override public final boolean equals(Object otherObject) { if (this == otherObject) return true; if (otherObject == null) return false; if (!(otherObject instanceof Poeple)) return false; Poeple other = (Poeple) otherObject; return ID == other.ID; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getID() { return ID; } public void setID(int iD) { ID = iD; }}class Student extends Poeple { // Student 可以有自己的域}class Teacher extends Poeple { // Teacher 可以有自己的域}2. 子类有自己的相等概念, 下面是一个范例程序.
class Poeple { private String name; private int age; @Override public boolean equals(Object otherObject) { if (this == otherObject) return true; if (otherObject == null) return false; if (getClass() != otherObject.getClass()) // 注意此处, 我们不能通过 instanceof 来判断 return false; Poeple other = (Poeple) otherObject; return name.equals(other.name) // 使用 equals 对象域 && age == other.age; // 使用 == 比较基本类型 } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}class Student extends Poeple { private int grade; @Override public boolean equals(Object otherObject) { if (!super.equals(otherObject)) // 此处需要调用父类的 equals 方法 return false; Student other = (Student) otherObject; return grade == other.grade; }}
从上面的例子可以看出, 想写出一个完美的 equals 还是很不容易的, 幸运的是 Apache Common 包有个 EqualsBuilder 类, 它能帮助我们很容易的实现 equals 方法.
--更多参见:
-- 声 明:转载请注明出处 -- Last Updated on 2012-05-18 -- Written by ShangBo on 2012-05-18 -- End