天天看點

【Java學習筆記之二十九】Java中的"equals"和"=="的用法及差別Java中的"equals"和"=="的用法及差別

在初學Java時,可能會經常碰到下面的代碼:

為什麼第4行和第5行的輸出結果不一樣?==和equals方法之間的差別是什麼?如果在初學Java的時候這個問題不弄清楚,就會導緻自己在以後編寫代碼時出現一些低級的錯誤。今天就來一起了解一下==和equals方法的差別之處。

  下面這個句話是摘自《Java程式設計思想》一書中的原話:

  “關系操作符生成的是一個boolean結果,它們計算的是操作數的值之間的關系”。

  這句話看似簡單,了解起來還是需要細細體會的。說的簡單點,==就是用來比較值是否相等。下面先看幾個例子:

  輸出結果為:

  n==m結果為true,這個很容易了解,變量n和變量m存儲的值都為3,肯定是相等的。而為什麼str1和str2兩次比較的結果不同?要了解這個其實隻需要了解基本資料類型變量和非基本資料類型變量的差別。

  在Java中遊8種基本資料類型:

  浮點型:float(4 byte), double(8 byte)

  整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)

  字元型: char(2 byte)

  布爾型: boolean(JVM規範沒有明确規定其所占的空間大小,僅規定其隻能夠取字面值"true"和"false")

  對于這8種基本資料類型的變量,變量直接存儲的是“值”,是以在用關系操作符==來進行比較時,比較的就是 “值” 本身。要注意浮點型和整型都是有符号類型的,而char是無符号類型的(char類型取值範圍為0~2^16-1).

  也就是說比如:

  int n=3;

  int m=3; 

  變量n和變量m都是直接存儲的"3"這個數值,是以用==比較的時候結果是true。

  而對于非基本資料類型的變量,在一些書籍中稱作為 引用類型的變量。比如上面的str1就是引用類型的變量,引用類型的變量存儲的并不是 “值”本身,而是于其關聯的對象在記憶體中的位址。比如下面這行代碼:

  String str1;

  這句話聲明了一個引用類型的變量,此時它并沒有和任何對象關聯。

  而 通過new String("hello")來産生一個對象(也稱作為類String的一個執行個體),并将這個對象和str1進行綁定:

  str1= new String("hello");

  那麼str1指向了一個對象(很多地方也把str1稱作為對象的引用),此時變量str1中存儲的是它指向的對象在記憶體中的存儲位址,并不是“值”本身,也就是說并不是直接存儲的字元串"hello"。這裡面的引用和C/C++中的指針很類似。

  是以在用==對str1和str2進行第一次比較時,得到的結果是false。是以它們分别指向的是不同的對象,也就是說它們實際存儲的記憶體位址不同。

  而在第二次比較時,都讓str1和str2指向了str指向的對象,那麼得到的結果毫無疑問是true。

  equals方法是基類Object中的方法,是以對于所有的繼承于Object的類都會有該方法。為了更直覺地了解equals方法的作用,直接看Object類中equals方法的實作。

  該類的源碼路徑為:C:\Program Files\Java\jdk1.6.0_14的src.zip 的java.lang路徑下的Object.java(視個人jdk安裝路徑而定)。

  下面是Object類中equals方法的實作:

  

【Java學習筆記之二十九】Java中的"equals"和"=="的用法及差別Java中的"equals"和"=="的用法及差別

  很顯然,在Object類中,equals方法是用來比較兩個對象的引用是否相等,即是否指向同一個對象。

  但是有些朋友又會有疑問了,為什麼下面一段代碼的輸出結果是true?

  要知道究竟,可以看一下String類的equals方法的具體實作,同樣在該路徑下,String.java為String類的實作。

  下面是String類中equals方法的具體實作:

【Java學習筆記之二十九】Java中的"equals"和"=="的用法及差別Java中的"equals"和"=="的用法及差別

  可以看出,String類對equals方法進行了重寫,用來比較指向的字元串對象所存儲的字元串是否相等。

  其他的一些類諸如Double,Date,Integer等,都對equals方法進行了重寫用來比較指向的對象所存儲的内容是否相等。

  總結來說:

  1)對于==,如果作用于基本資料類型的變量,則直接比較其存儲的 “值”是否相等;

    如果作用于引用類型的變量,則比較的是所指向的對象的位址

  2)對于equals方法,注意:equals方法不能作用于基本資料類型的變量

    如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的位址;

    諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的對象的内容。