Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

สัญญา (Contract) ระหว่าง equals() และ hashCode() methods ใน Java

ทุก Java object มีเมธอดสำคัญ 2 ตัวคือ equals() และ hashCode() และเมธอดเหล่านี้ถูกออกแบบให้ override ตาม general contract เฉพาะของมัน คลาส Object เป็น parent class ของทุกคลาส การ implement เริ่มต้นของเมธอดทั้งสองนี้มีอยู่ในแต่ละคลาสแล้ว อย่างไรก็ตาม เราสามารถ override เมธอดเหล่านี้ตามความต้องการได้

hashCode() Method

public int hashCode()

เมธอดนี้คืนค่า integer ซึ่งเรียกว่า hash code value ของออบเจ็กต์ ทุก Object ขณะสร้างจะถูกกำหนดค่า 32-bit signed int ที่ไม่ซ้ำกัน ค่านี้คือ hash code value ของออบเจ็กต์นั้น

General contract ของ hashCode() method

  • เมธอด hashCode() ควรคืนค่า integer เดียวกันสำหรับออบเจ็กต์เดียวกัน ทุกครั้งที่เรียก เมธอดนี้ ยกเว้นค่าที่เก็บในออบเจ็กต์ถูกแก้ไข
  • ถ้าออบเจ็กต์สองตัวเท่ากัน (ตาม equals() method) แล้ว hashCode() ควรคืนค่า integer เดียวกันสำหรับทั้งสองออบเจ็กต์
  • แต่ ไม่จำเป็น ที่ hashCode() จะคืนค่าที่แตกต่างกันสำหรับออบเจ็กต์ที่ไม่เท่ากัน (ตาม equals() method)

equals() Method

public boolean equals(Object obj)

เมธอด equals() ของ Object class ตรวจสอบความเท่ากันของออบเจ็กต์ และคืนค่า true หรือ false ตามลำดับ การ implement เริ่มต้นจาก Object class ตรวจสอบความเท่ากันจาก reference ว่าอ้างอิงออบเจ็กต์เดียวกันหรือไม่ ไม่ได้ตรวจสอบค่าหรือ state ของออบเจ็กต์ แต่เราสามารถ override เมธอดนี้เพื่อให้ implementation เปรียบเทียบ state หรือ value ของออบเจ็กต์ได้

General contract ของ equals() method

สำหรับ reference variables a, b, c ที่ไม่เป็น null

  • a.equals(a) ควรคืน true เสมอ
  • a.equals(b) ควรคืน true ก็ต่อเมื่อ b.equals(a) คืน true
  • ถ้า a.equals(b) คืน true และ b.equals(c) คืน true แล้ว a.equals(c) ควรคืน true
  • การเรียก a.equals(b) หลายครั้ง ควรคืน true ตลอด หรือ false ตลอด หากค่าของออบเจ็กต์ไม่ได้ถูกแก้ไขสำหรับออบเจ็กต์ใดออบเจ็กต์หนึ่ง
  • a.equals(null) ควรคืน false

ดังนั้น จึงจำเป็นต้อง override เมธอด hashCode() ของ Object class หากเรา override เมธอด equals()

ตัวอย่าง

public class MainClass {
    public static void main(String[] args) {
        MainClass mainClass = new MainClass();
        TestClass obj1 = new TestClass(1);
        TestClass obj2 = new TestClass(1);
        mainClass.test1(obj1, obj2);
        TestClass obj3 = new TestClass(1);
        TestClass obj4 = new TestClass(2);
        mainClass.test2(obj3, obj4);
    }
    public void test1(TestClass obj1, TestClass obj2) {
        if (obj1.equals(obj2)) {
            System.out.println("Object One and Object Two are equal");
        } else {
            System.out.println("Object One and Object Two are not equal");
        }
    }
    public void test2(TestClass obj3, TestClass obj4) {
        if (obj3.equals(obj4)) {
            System.out.println("Object Three and Object Four are equal");
        } else {
            System.out.println("Object Three and Object Four are not equal");
        }
    }
}
class TestClass {
    private int val;
    TestClass(int val) {
        this.val = val;
    }
    public int getValue() {
        return val;
    }
    @Override
    public boolean equals(Object o) {
        // null check
        if (o == null) {
            return false;
        }
        // this instance check
        if (this == o) {
            return true;
        }
        // instanceof Check and actual value check
        if ((o instanceof TestClass) && (((TestClass) o).getValue() == this.val)) {
            return true;
        }
        else {
            return false;
        }
    }
    @Override
    public int hashCode() {
        int result = 0;
        result = (int) (val / 11);
        return result;
    }
}

ผลลัพธ์

Object One and Object Two are equal
Object Three and Object Four are not equal