下面先给出编写一个完美的equals方法的建议:
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(this.getClass != otherObject.getClass()) return false;
若果所有的子类都拥有相同的语义就使用instanceof检测:
if( ! (otherObject instanceof ClassName)) return false;
5) 将otherObject对象转变为相应的类类型变量:
ClassName other = (ClassName) otherObject;
6)现在对所有需要比较的域进行比较。使用 == 比较基本数据类型,使用equals比较对象域,如果所有的域都匹配就返回true否则返回false
为了防备对象域可能为null的情况,需要使用Objects.equals方法,其源码如下:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
7)如果子类重写了equals,就要在其中包含调用super.equals(otherObject)。
equals方法有下面的特性:
1 自反性 即X.equals(X)返回true
2 对称性 即X.equals(Y)返回true ,Y.equals(X)返回true
3 传递性 即X.equals(Y)返回true ,Y.equals(Z)返回true,Z.equals(X)返回true
4 一致性 xy引用的对象没有发生变化,反复比较应该是一样的
5 对于任意非空引用X,X.equals(null)返回false
上面介绍的getClass进行相等检测和instaceof进行相等检测是不是说的大家头疼的要死,下面可以从两个截然不同的情况看一下这个问题:
1 如果子类能够拥有自己相等的概念,则对称性需求将强制采用getClass进行检测
2 如果是由超类决定相等的概念,那么就可以使用instanceof来进行检测,这样可以在不同子类对象之间进行相等的比较
代码应用实例:
package com.heima.equals;
import java.time.LocalDate;
import java.util.Objects;
public class Empolyee {
private String name;
private double salary;
public Empolyee() {
super();
}
public Empolyee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public boolean equals(Object otherObject) { //第一步
if (this == otherObject) //第二步
return true;
if (otherObject == null) //第三步
return false;
if (getClass() != otherObject.getClass()) //第四步 因为在子类中比较的内容会有变化,所以使用getClass
return false;
Empolyee other = (Empolyee) otherObject; //第五步
return Objects.equals(name,other.name) && salary ==other.salary;//第六步
}
}
package com.heima.equals;
import java.time.LocalDate;
import java.util.Objects;
public class Mannger extends Empolyee {
private double bonus;
public Mannger() {
super();
}
public Mannger(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
@Override
public double getSalary() {
return this.bonus + super.getSalary();
}
@Override
public boolean equals(Object otherObject) {
// TODO Auto-generated method stub
if(! super.equals(otherObject)) return false;
Mannger other = (Mannger)otherObject;
return bonus == other.bonus;
}
}