面試必問一:Java 中 == 和 equals 的區別你知道嗎

面試必問一:Java 中 == 和 equals 的區別你知道嗎

前言

關於這個問題,通常初中級面試中都會遇到,還記得我當初實習找工做的時候也遇到了這個問題,如今都還記得本身是怎麼回答的:== 是基本類型比較,equals 是對象比較,不懂 hashCode,想起來簡直慘不忍睹。因而找了一點小時間,研究了一番整理成文章供你們參考。java

== 是什麼?

在《java核心技術卷 1》中將==歸類於關係運算符;面試

==經常使用於相同的基本數據類型之間的比較,也可用於相同類型的對象之間的比較;算法

  • 若是==比較的是基本數據類型,那麼比較的是兩個基本數據類型的值是否相等;
  • 若是==是比較的兩個對象,那麼比較的是兩個對象的引用,也就是兩個對象是否爲同一個對象,並非比較的對象的內容;

下面舉例說明:bash

public class Test {
    public static void main(String[] args){
        // 對象比較
        User userOne = new User();
        User userTwo = new User();
        System.out.println("userOne==userTwo : "+(userOne==userTwo));

        // 基本數據類型比較
        int a=1;
        int b=1;
        char c='a';
        char d='a';
        System.out.println("a==b : "+(a==b));
        System.out.println("c==d : "+(c==d));
    }
}
class User {
     String userName;
     String password;
}


運行結果:

userOne==userTwo : false
a==b  :  true
c==d  :  true

複製代碼

對象 userOne 和 userTwo 雖然都是 User 的示例,但對於了堆內存的不一樣區域,所以他們的引用也不一樣,因此爲 false;a 和 b 都是基本類型所以對比的是指,結果爲 true ; c 和 d 也是基本類型 通 a 和 b.ide

equals 是什麼鬼?

在《java核心技術卷 1》中對 Object 類的描述:Object 類是java中全部類的始祖,在java中每一個類都是由Object類擴展而來;每一個類都默認繼承Object類,因此每個類都有Object類中的方法;從而每個類都有equals方法;函數

equals方法主要用於兩個對象之間,檢測一個對象是否等於另外一個對象;ui

下邊來看一看Object類中equals方法的源碼:this

public boolean equals(Object obj) {
        return (this == obj);
    }

複製代碼

能夠看出來Object類中的equals方法用的仍是==,也就是比較的兩個對象的引用是否相等,並非根據對象中的屬性來判斷兩個對象是否相等的;也就是說咱們本身定義的類中,若是沒有重寫equals方法,實際上仍是用的==來比較的兩個對象,則用equals方法比較的結果與用==比較的結果是同樣的;spa

java語言規範要求equals方法具備如下特性:.net

  • 自反性。對於任意不爲null的引用值x,x.equals(x)必定是true。
  • 對稱性)。對於任意不爲null的引用值x和y,當且僅當x.equals(y)是true時,y.equals(x)也是true。
  • 傳遞性。對於任意不爲null的引用值x、y和z,若是x.equals(y)是true,同時y.equals(z)是true,那麼x.equals(z)必定是true。
  • 一致性。對於任意不爲null的引用值x和y,若是用於equals比較的對象信息沒有被修改的話,屢次調用時x.equals(y)要麼一致地返回true要麼一致地返回false。
  • 對於任意不爲null的引用值x,x.equals(null)返回false。

下面再來看一看比較典型的一個類;

  • String

這是jdk中的類,並且該類重寫了equals方法;

下面來看一看該類中的equals方法源碼:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    
複製代碼

從源碼能夠看出equals方法是進行的內容比較;

舉個例子:

public class Test {
    public static void main(String[] args){
        // 未重寫equals方法的類
        User userOne = new User();
        User userTwo = new User();
        System.out.println("userOne.equals(userTwo) : "+(userOne.equals(userTwo)));
        //重寫了equals方法的類
        String a="1111";
        String b="1111";
        System.out.println("a.equals(b) : "+(a.equals(b)));
    }
}
class User {
     String userName;
     String password;
}
複製代碼

下面是運行結果:

userOne.equals(userTwo) :  false
a.equals(b)  : true
複製代碼

說明 String 對比的是對象的值。

hashCode 有什麼做用?

hashCode也是Object類中的方法;下面看一下hashCode方法的源碼:

public native int hashCode();
複製代碼

該方法是一個本地方法;該方法返回對象的散列碼(int類型);它的實現是根據本地機器相關的;

下面是百度百科對hash的說明:

Hash,通常翻譯作散列、雜湊,或音譯爲哈希,是把任意長度的輸入(又叫作預映射pre-image)經過散列算法變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間一般遠小於輸入的空間,不一樣的輸入可能會散列成相同的輸出,因此不可能從散列值來肯定惟一的輸入值。簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。

散列函數能使對一個數據序列的訪問過程更加迅速有效,經過散列函數,數據元素將被更快地定位

  1. Java對於eqauls方法和hashCode方法是這樣規定的:
  • 若是兩個對象相同,那麼它們的hashCode值必定要相同;
  • 若是兩個對象的hashCode相同,它們並不必定相同。
  • equals()相等的兩個對象,hashcode()必定相等;equals()不相等的兩個對象,卻並不能證實他們的hashcode()不相等。
  1. 什麼地方使用hashCode?

Hashcode值主要用於基於散列的集合,如HashMap、HashSet、HashTable…等等;

這些集合都使用到了hashCode,想象一下,這些集合中存有大量的數據,假若有一萬條,咱們向其中插入或取出一條數據,插入時如何判斷插入的數據已經存在?取出時如何取出相同的數據?難道一個一個去比較?這時候,hashCode就提現出它的價值了,大大的減小了處理時間;這個有點相似於MySQL的索引;

  1. 舉例
public class Test {
    public static void main(String[] args){
        //未重寫hashCode的類
        User userOne = new User("aa","11");
        User userTwo = new User("aa","11");
        System.out.println(userOne.hashCode());
        System.out.println(userTwo.hashCode());
        //重寫hashCode的類
        String a = new String("string");
        String b = new String("string");
        System.out.println(a.hashCode());
        System.out.println(b.hashCode());
    }
}
class User {
    private String userName;
    private String password;
    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
}

運行結果:

752848266
815033865
-891985903
-891985903

複製代碼

根據結果能夠看出:userOne 和 userTwo 的 hashCode 值不一致;a 和 b 的 hashCode 一致。


PS: 歡迎關注公衆號 [ Java極客技術 ]

Java 極客技術公衆號,是由一羣熱愛 Java 開發的技術人組建成立,專一分享原創、高質量的 Java 文章。若是您以爲咱們的文章還不錯,請幫忙讚揚、在看、轉發支持,鼓勵咱們分享出更好的文章。


參考文章:

Java中的equals()和hashcode()之間關係
HashCode的做用原理和實例解析
Guide to hashCode() in Java
equals() and hashCode() methods in Java

相關文章
相關標籤/搜索