Java关于equals()方法和“==”逻辑运算符的区别简介
由于Java并沒有像C++那樣的重載運算符的機制,因此在比較類對象時,Java沒有辦法像C++那樣通過重載==運算符來直接比較兩個類對象是否相等,只能使用Object類中的equals()方法來對類對象進行比較,但是equals()方法中有一些地方值得說明。
先上代碼:
import java.util.*; public class Test {public static void main(String[] args) {Integer a1 = new Integer(10);Integer a2 = new Integer(10);System.out.println(a1==a2);System.out.println(a1.equals(a2));} }輸出結果是:
false
true
這里應該注意到,對于類而言,創建類對象的時候,Java使用引用數據類型來指向真正的對象空間。也就是說,當我創建一個a1時,這個時候a1只是一個Integer類的引用,它儲存在棧中,而new Integer(10)這行代碼才是真正創建了一個Integer對象,并將這個對象設置為10,這個對象儲存在堆中。當使用==運算符對比a1和a2時,結果是false,這是因為==運算符對于類對象來說比較的是引用而不是真正的對象,在棧中,a1這個引用指向的對象空間和a2引用指向的對象空間并不相同(因為a1和a2用了兩次new開辟的空間),因此使用==運算符結果自然是false。這個時候要想獲得true,就應該使用equals方法,這個方法才是真正到達a1和a2指向的對象空間,對這兩個對象進行比較,從而得到true。
接下來,針對Integer數組來對==和equals進行說明:
public class Test {public static void main(String[] args) {Integer[] a3 = new Integer[] {new Integer(1), new Integer(2), new Integer(3)};Integer[] a4 = new Integer[] {new Integer(1), new Integer(2), new Integer(3)};System.out.println(a3==a4);System.out.println(a3.equals(a4));} }這里創建的是Integer數組,輸出結果為:
false
false
本來第二個輸出應該得到true,但是事實卻相反。原因在于,創建數組時,數組名本身為引用,數組內的元素也是引用,拿a3來說,創建a3時,Java注意到它有1,2,3這三個元素,因此它在棧中創建一個引用,這個引用名字是a3,這個引用指向一個含有三個引用的集合,也就是一個數組,這個集合的元素名分別是a3[0],a3[1],a3[2],請注意,這三個元素都是引用,每個元素指向堆中的一個對象空間,那個空間存儲的才是真正的數據。因此對a3和a4使用equals進行比較的時候仍然無法直接比較真正的對象。要想得到true,要使用另一個方法,即Arrays.equals()方法(這個方法位于util包中,在使用這個方法之前,應該添加import java.util.*;這行代碼以導入這個包),這個方法不同于對象本身的方法,它接受兩個數組參數,對它們進行比較。
這行的輸出結果是true,當然,也可以對數組內的元素(引用)依次進行比較:
System.out.println(a3[0].equals(a4[0]));這樣也可以得到true,這也從側面證明了數組a3和a4內的元素,原來只不過都是引用罷了。
請注意,前面創建a3和a4,里面的元素都是使用new Integer(參數)來創建的,但是Java對基本數據類型和類對象之間一個自動包裝機制,如果代碼這么寫:
public class Test {public static void main(String[] args) {Integer[] a5 = new Integer[] {1, 2, 3};Integer[] a6 = new Integer[] {1, 2, 3};System.out.println(a5==a6);System.out.println(a5.equals(a6));System.out.println(a5[1]==a6[1]);System.out.println(a5[1].equals(a6[1]));} }這里的輸出是:
false
false
true
true
這個輸出是令我疑惑的地方,由于自動包裝機制的存在,a5的元素可以直接用整數來填充,這樣一來,我知道a5是一個引用,但我無法得知a5內的元素是否是引用,如果是引用,那么第三行輸出,即a5[1]==a6[1]應該得到false,如果不是引用,那么第二行輸出,即a5.equals(a6)應該得到true,這個自動包裝機制讓我很是無法理解這里的輸出,如果您看到了這里,并且知道其中玄機的話,懇請您告訴我其中的原因。
現在,我們來拋開Java自帶的類,來對我們自定義的類使用equals()方法,看看會是什么樣子:
class A {private int a;public A(int a) {this.a = a;} } public class Test {public static void main(String[] args) {A a7 = new A(10);A a8 = new A(10);System.out.println(a7==a8);System.out.println(a7.equals(a8));} }在這里我定義了一個簡單的類A,它含有一個私有的int數據,并且通過構造器來對這個私有int進行賦值。
這里的輸出結果是:
false
false
這里有一點,為什么前面對a1和a2(兩者都是Integer引用)使用equals()就可以得出true,而這里卻無法得出true?原因在于,位于根類Object的equals()方法在比較時默認比較的仍然是引用,在類A中,我沒有對繼承自Object的equals()方法進行覆蓋,因此對A對象調用equals()方法時比較的仍然是引用(相當于使用了==運算符),而Integer能得出true的原因就是Java自帶的包裝類都覆蓋了equals方法,從而能得出正確結果,對于類A來說,使equals方法進行正確行為的解決方法就是覆蓋equals方法,因此可以在類A中添加方法equals():
添加了equals方法后的類A可以就可以得出正確的比較結果。
?
總結
以上是生活随笔為你收集整理的Java关于equals()方法和“==”逻辑运算符的区别简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java构造器、静态对象、非静态对象等的
- 下一篇: java service层 事务_Jav