用equals方法來比較對象是否相等的。于是繼續(xù)找到equals的源代碼,如下:
public boolean equals(Object obj) {
return (this == obj);
}
equals 方法是 java.lang.Object 類的方法。
有兩種用法說明:
(1)對于字符串變量來說,使用“==”和“equals()”方法比較字符串時,其比較方法不同。
“==”比較兩個變量本身的值,即兩個對象在內(nèi)存中的首地址。
“equals()”比較字符串中所包含的內(nèi)容是否相同。
"=="比"equal"運(yùn)行速度快,因?yàn)?quot;=="只是比較引用.
詳述:
①==和equals的實(shí)質(zhì)。
在JAVA中利用"=="比較變量時,系統(tǒng)使用變量在"棧"中所存的值作為比較的依據(jù)。
基本數(shù)據(jù)類型在"棧"中存的是其內(nèi)容值,而對象類型在"棧"中存的是地址,這些地址指向"堆"中的對象。
java.lang包中的Object類有public boolean equals(Object obj)方法,它比較兩個對象是否相等。
其它對象的equals方法僅當(dāng)被比較的兩個引用指向的對象內(nèi)容相同時,對象的equals()方法返回true。
總之,"=="和"!="比較的是地址.也可認(rèn)為"=="和"!="比較的是對象句柄;而equals()比較的是對象內(nèi)容.或者說,,"=="和"!="比較的是"棧"中的內(nèi)容,而equals()比較的是"堆"中的內(nèi)容.
②==操作符。專門用來比較兩個變量的值是否相等,也就是用于比較變量所對應(yīng)的內(nèi)存中所存儲的數(shù)值是否相同,要比較兩個基本類型的數(shù)據(jù)或兩個引用變量是否相當(dāng),只能用==操作符。
Java的基本數(shù)據(jù)類型為(char,byte,short,int,long,float,double,boolean)。
如果一個變量指向的數(shù)據(jù)是對象類型的,那么,這時候涉及了兩塊內(nèi)存,對象本身占用一塊內(nèi)存(對內(nèi)存),變量本身也占用一塊內(nèi)存,例如Object obj = new Object()變量obj是一個內(nèi)存,new Object()是一個內(nèi)存,此時,變量所對應(yīng)的內(nèi)存中存儲的數(shù)據(jù)就是對象占用的那塊內(nèi)存的首地址。對于指向?qū)ο髢?nèi)存的變量,如果要比較兩個變量是否指向同一個對象,即要看這兩個變量所對應(yīng)的內(nèi)存中的數(shù)值是否相等,這時候就需要用==操作符進(jìn)行比較。
③構(gòu)造器形成的差別。對于String和Integer來說,由于他們特有的創(chuàng)建對象的方式。使用構(gòu)造器和不使用構(gòu)造器得到一個對象,==方法比較所產(chǎn)生的結(jié)果是不同的。 String a = “abc”; String b = "abc"; 此時a==b得到結(jié)果為true。String a = new String("abc"); String b = new String("abc");此時a==b得到的結(jié)果為false。Integer a = 1; Integer b = 1;此時a==b的結(jié)果是true。Integer a = new Integer(1); Integer b = new Integer(1);此時a==b得到的結(jié)果為false。
通過這一點(diǎn)其實(shí)我們也能夠更加容易理解==對內(nèi)存的實(shí)際操作,實(shí)際執(zhí)行的是近似于基本類型比較。
String對象和字符串連接池:
引號內(nèi)包含文本是String類特有創(chuàng)建對象的方式.但是"=="返回的結(jié)果是true,為什么呢?因?yàn)樵贘VM內(nèi),存在字符串池,其中保存著很多 String對象,并且可以被共享使用,因此它提高了效率.字符串池由String類維護(hù),我們可以調(diào)用intern()方法來訪問字符串池。當(dāng)運(yùn)用引號內(nèi)包含文本創(chuàng)建對象時,所創(chuàng)建的對象是加入到字符串池里面的.如果要創(chuàng)建下一個字符串對象,JVM首先會到字符串池中尋找,是否存在對應(yīng)的字符串對象,如果存在,則返回一個己存在對象的對象的引用給要創(chuàng)建的對象引用.如果不存在,才會創(chuàng)建一個新的對象,并返回一個新對象的對象引用給要創(chuàng)建的對象引用.以上這段話理解起來可能比較拗口.用代碼理解就是str2和str1是兩個對象引用,并指向了同一個對象.所以'=='返回的是true.
只有引號內(nèi)包含文本創(chuàng)建對象才會將創(chuàng)建的對象放入到字符串池。String str = new String("abc")這種方法創(chuàng)建的字符串對象是不放入到字符串池的。所以,引號內(nèi)包含文本創(chuàng)建對象的性能要比后來那種方法創(chuàng)建字符串對象的性能要好。
String str1 = "abc";
String str2 = "abc";
String str3 = str1+str2; //這種創(chuàng)建方式是不放入字符串池的.
String str4 = str1+"cd"; //這種創(chuàng)建方式是不放入字符串池的.
String str5 = "ab"+str2; //這種創(chuàng)建方式是不放入字符串池的.
String str6 = "ab"+"cd"; //這種創(chuàng)建方式是放入字符串池的.這種情況實(shí)際上是創(chuàng)建了1個對象,abcd"1個對象
String str7 = "abcd";
System.out.println(str1==str2); //返回ture
System.out.println(str6==str7); //返回ture
另一個問題:
我們首先來看一段 Java代碼:
String str=new String("abc");
緊接著這段代碼之后的往往是這個問題,那就是這行代碼究竟創(chuàng)建了幾個String對象呢?相信大家對這道題并不陌生,答案也是眾所周知的,2個。接下來我們就從這道題展開,一起回顧一下與創(chuàng)建String對象相關(guān)的一些JAVA知識。
我們可以把上面這行代碼分成String str、=、"abc"和new String()四部分來看待。String str只是定義了一個名為str的String類型的變量,因此它并沒有創(chuàng)建對象;=是對變量str進(jìn)行初始化,將某個對象的引用(或者叫句柄)賦值給它,顯然也沒有創(chuàng)建對象;現(xiàn)在只剩下new String("abc")了。那么,new String("abc")為什么又能被看成"abc"和new String()呢?我們來看一下被我們調(diào)用了的String的構(gòu)造器:
Java代碼
public String(String original) {
//other code ...
}
大家都知道,我們常用的創(chuàng)建一個類的實(shí)例(對象)的方法有以下兩種:
我們正是使用new調(diào)用了String類的上面那個構(gòu)造器方法創(chuàng)建了一個對象,并將它的引用賦值給了str變量。同時我們注意到,被調(diào)用的構(gòu)造器方法接受的參數(shù)也是一個String對象,這個對象正是"abc"。
使用new創(chuàng)建對象是調(diào)用Class類的newInstance方法,利用反射機(jī)制創(chuàng)建對象。
④equals方法。用于比較兩個獨(dú)立對象的內(nèi)容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨(dú)立的。例如,對于下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創(chuàng)建了兩個對象,然后用a,b這兩個變量分別指向了其中一個對象,這是兩個不同的對象,他們的首地址是不同的,即a和b中存儲的數(shù)值是不相同的,所以,表達(dá)式a==b即返回false,而這兩個對象中內(nèi)容是相同的,所以,表達(dá)式a.equals(b)將返回true。
在實(shí)際開發(fā)中,我們經(jīng)常要比較傳遞進(jìn)行來的字符串內(nèi)容是否相等,許多人稍不注意就使用==進(jìn)行比較了,這是錯誤的,有大量這樣的錯誤。記住,字符串的比較基本都是使用equals方法。
⑤如果一個類沒有定義equals方法。它將繼承Object類的equals方法,Object類的equals方法的實(shí)現(xiàn)代碼如下:
boolean equals(Object o){
return this==o;
}
這說明,如果一個類沒有自己定義equals方法,它默認(rèn)的equals方法(從Object類繼承的)就是使用==操作符,也是比較兩個變量指向的對象是否是同一個對象,這時候使用equals和使用==會得到同樣的結(jié)果,如果比較的是兩個獨(dú)立的對象則總返回false。如果你編寫的類希望能夠比較該類創(chuàng)建的兩個實(shí)例對象的內(nèi)容是否相同,那么你必須覆蓋equals方法,由你自己寫代碼來決定在什么情況即可以認(rèn)為兩個對象的內(nèi)容是相同的。