Java中的equals、==、hashCode

參考淺談Java中的equals和==
Java 中正確使用 hashCode 和 equals 方法

一、==

結論:
如果作用于基本數據類型的變量,則直接比較其存儲的 “值”是否相等;
如果作用于引用類型的變量,則比較的是所指向的對象的地址

public class Main {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int n=3;
        int m=3;
        
        System.out.println(n==m);
        
        String str = new String("hello");
        String str1 = new String("hello");
        String str2 = new String("hello");
        
        System.out.println(str1==str2);
        
        str1 = str;
        str2 = str;
        System.out.println(str1==str2);
    }
}
//ture false true
二、equals方法

1.如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址;下面是Object類中equals方法的實現:

Paste_Image.png

2.equals方法不能作用于基本數據類型的變量。諸如String、Double,Date,Integer,Date等類對equals方法進行了重寫的話,比較的是所指向的對象的內容。下面是String類中equals方法的具體實現:

Paste_Image.png
三、haseCode
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;
 
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}

上面的Employee類只是有一些非常基礎的屬性和getter、setter.現在來考慮一個你需要比較兩個employee的情形。

public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();
 
        e1.setId(100);
        e2.setId(100);
        //Prints false in console
        System.out.println(e1.equals(e2));
    }
}

毫無疑問,上面的程序將輸出false,但是,事實上上面兩個對象代表的是通過一個employee。真正的商業邏輯希望我們返回true。 為了達到這個目的,我們需要重寫equals方法。

public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}

測試一下:

import java.util.HashSet;
import java.util.Set;
 
public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();
 
        e1.setId(100);
        e2.setId(100);
 
        //Prints 'true'
        System.out.println(e1.equals(e2));
 
        Set<Employee> employees = new HashSet<Employee>();
        employees.add(e1);
        employees.add(e2);
        //Prints two objects
        System.out.println(employees);
    }
}

如果兩個employee對象equals返回true,Set中應該只存儲一個對象才對,問題在哪里呢? 我們忘掉了第二個重要的方法hashCode()。就像JDK的Javadoc中所說的一樣,如果重寫equals()方法必須要重寫hashCode()方法。我們加上下面這個方法,程序將執行正確。

@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }

需要注意的事情

  • 盡量保證使用對象的同一個屬性來生成hashCode()和equals()兩個方法。在我們的案例中,我們使用員工id。
  • eqauls方法必須保證一致(如果對象沒有被修改,equals應該返回相同的值)
  • 任何時候只要a.equals(b),那么a.hashCode()必須和b.hashCode()相等。兩者必須同時重寫。
  • 如果你使用ORM處理一些對象的話,你要確保在hashCode()和equals()對象中使用getter和setter而不是直接引用成員變量。因為在ORM中有的時候成員變量會被延時加載,這些變量只有當getter方法被調用的時候才真正可用。例如在我們的例子中,如果我們使用e1.id == e2.id則可能會出現這個問題,但是我們使用e1.getId() == e2.getId()就不會出現這個問題。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容