equals方法使用小结
先来简单小结一下equals的用法:
1.首先如果只是基本数据类型,那么判断两个变量是否相等用 == 即可
2.比较对象,有两种情况:
一种就是使用java已经给我们提供好的类。如包装器类型,如Boolean、Double、Integer,这些只要直接使用equals比较即可,因为他们内部已经重写了equals和hashCode方法,所以我们可以直接使用。
二种当然也是比较经常使用的自定义类型。如果要比较自定义的的两个类的对象是否相等,就需要我们重写equals和hashCode方法。如下:
@Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (otherObject == null) {
return false;
}
if (getClass() != otherObject.getClass()) {
return false;
}
Employee other = (Employee)otherObject;
boolean flag = name.equals(other.getName()) && salary.equals(other.getSalary()) && hireDay.equals(other.getHireDay());
return flag;
}
@Override
public int hashCode() {
return name.hashCode() + hireDay.hashCode() + salary.hashCode();
}
这两者是对应的,必须都要重写。
==================================代码示例======================
本代码摘抄至‘Java核心技术’,因为版本的问题,修改的些许代码。以下直接贴出代码。。
1.雇员类:
package com.lin.model;
import java.time.LocalDate;
/**
* 雇员类
*
* @author linrui
* @date 2019/03/27
* */
public class Employee {
private String name;
private Double salary;
private LocalDate hireDay;
public Employee(String name, Double salary, int year, int month, int day) {
this.name = name;
this.salary = salary;
this.hireDay = LocalDate.of(year, month, day);
}
public String getName() {
return name;
}
public Double getSalary() {
return salary;
}
public LocalDate getHireDay() {
return hireDay;
}
public void raiseSalary(Double byPercent) {
double raise = salary * byPercent/100;
salary += raise;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", salary=" + salary +
", hireDay=" + hireDay +
'}';
}
@Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (otherObject == null) {
return false;
}
if (getClass() != otherObject.getClass()) {
return false;
}
Employee other = (Employee)otherObject;
boolean flag = name.equals(other.getName()) && salary.equals(other.getSalary()) && hireDay.equals(other.getHireDay());
return flag;
}
@Override
public int hashCode() {
return name.hashCode() + hireDay.hashCode() + salary.hashCode();
}
}
2.经理类(雇员类的子类)
package com.lin.model;
import java.time.LocalDate;
/**
* 经理类
*
* @author linrui
* @date 2019/03/27
* */
public class Manager extends Employee{
private Double bonus;
public Manager(String name, Double salary, int year, int month, int day) {
super(name, salary, year, month, day);
this.bonus = new Double(0);
}
@Override
public Double getSalary() {
Double baseSalary = super.getSalary();
return baseSalary + bonus;
}
public void setBonus(Double bonus) {
this.bonus = bonus;
}
@Override
public boolean equals(Object otherObject) {
if (!super.equals(otherObject)) {
return false;
}
Manager other = (Manager)otherObject;
return bonus.equals(other.bonus);
}
@Override
public int hashCode() {
return super.hashCode() + 17 * bonus.hashCode();
}
@Override
public String toString() {
return super.toString() + "[bonus=" +bonus + "]";
}
}
3.测试代码
package com.lin.test;
import com.lin.model.Employee;
import com.lin.model.Manager;
/**
* 测试类
*
* @author linrui
* @date 2019/03/27
* */
public class EqualsTest {
public static void main(String[] args) {
// Employee alice1 = new Employee("Alice Adams", new Double(7500), 1987, 12, 15);
// Employee alice2 = alice1;
// Employee alice3 = new Employee("Alice Adams", new Double(7500), 1987, 12, 15);
// Employee bob = new Employee("Bob Brandson", new Double(5000), 1989, 10, 1);
//
// System.out.println("alice1 == alice2:" + (alice1 == alice2));
//
// System.out.println("alice1 == alice3:" + (alice1 == alice3));
//
// System.out.println("alice1.equals(alice3)):" + alice1.equals(alice3));
//
// System.out.println("alice1.equals(bob)):" + alice1.equals(bob));
//
// System.out.println("bob.toString():" + bob);
//
Manager carl = new Manager("Carl Cracker", new Double(8000), 1987, 12, 15);
Manager boss = new Manager("Carl Cracker", new Double(8000), 1987, 12, 15);
boss.setBonus(new Double(5000));
carl.setBonus(new Double(5000));
// System.out.println("boss.toString()" + boss);
System.out.println("carl.equals(boss):" + carl.equals(boss));
// System.out.println("alice1.hashCode():" + alice1.hashCode());
// System.out.println("alice3.hashCode():" + alice3.hashCode());
// System.out.println("bob.hashCode():" + bob.hashCode());
// System.out.println("carl.hashCode():" + carl.hashCode());
}
}
4.使用小结:
直接看上面的测试类,注释掉的地方都是很好理解的,就不在累赘。
因为Manager中的equals方法调用了父类Employee的equals方法
所以,直接将断点打到Employee的equals()方法中,然后debug跑起来,
虽然otherObject被强制转换成了Employee,但是other并不是一个对象,而是指向otherObject对象的一个引用,而实际上otherObject是一个Manager对象。
所以,在调用otherObject.getSalary()方法的时候,实际上执行的是Manager中的方法
所以最终的输出结果是flase。
看明白的话自然还是好理解的,但是一开始我看的时候发现怎么想都不太对,于是就去跟踪源码,发现了是这里的问题。其实要是想简单明白,就直接将Manager中的equals方法重写为以下这个就好理解了。
@Override
public boolean equals(Object otherObject) {
if (this == otherObject) {
return true;
}
if (otherObject == null) {
return false;
}
if (getClass() != otherObject.getClass()) {
return false;
}
Manager other = (Manager)otherObject;
return bonus.equals(other.bonus);
}