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);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章