String中的“equal方法”和“==”
二話不說,先來說下重寫的事情:
在Java中,String 、Math、還有Integer、Double。。。。等這些封裝類重寫了Object中的equals()方法,讓它不再比較其對象在內(nèi)存中的地址,而是比較對象中實(shí)際包含的整數(shù)的值,即比較的是內(nèi)容。再強(qiáng)調(diào)一次,Object的equals()方法比較的是地址值,所以O(shè)bject equals相等時(shí),其hashcode必然相等,因?yàn)槎际菍ο蟮牡刂?#xff0c;所以自己定義的類如果要加入到集合類中一定要記得重寫這兩個(gè)方法。
在Eclipse中重寫hashcode和equals方法使相當(dāng)方便的,只需要右鍵->source->Generate hashcode() and equals()便可以了
意思是 :非Object聲明的對象,都已經(jīng)重寫了equals方法,不需要我們自己重寫了。,Object聲明的必須重寫才可以比較內(nèi)容。而非地址。
對于 數(shù)值型的,我們就用==比較,對于其他類型的,自己選擇,建議我們可以用使用Stringutils來避免空指針的問題。
對于String中的“equal方法”和“==”一直有點(diǎn)混肴,今天重新看了一下他們兩點(diǎn)的區(qū)別,記錄下來讓自己以后不在忘記!
"=="和equals方法究竟有什么區(qū)別?
(單獨(dú)把一個(gè)東西說清楚,然后再說清楚另一個(gè),這樣,它們的區(qū)別自然就出來了,混在一起說,則很難說清楚)
==操作符專門用來比較兩個(gè)變量的值是否相等,也就是用于比較變量所對應(yīng)的內(nèi)存中所存儲(chǔ)的數(shù)值是否相同,要比較兩個(gè)基本類型的數(shù)據(jù)或兩個(gè)引用變量是否相等,只能用==操作符。
如果一個(gè)變量指向的數(shù)據(jù)是對象類型的,那么,這時(shí)候涉及了兩塊內(nèi)存,對象本身占用一塊內(nèi)存(堆內(nèi)存),變量也占用一塊內(nèi)存,例如Objet obj = newObject();變量obj是一個(gè)內(nèi)存,new Object()是另一個(gè)內(nèi)存,此時(shí),變量obj所對應(yīng)的內(nèi)存中存儲(chǔ)的數(shù)值就是對象占用的那塊內(nèi)存的首地址。對于指向?qū)ο箢愋偷淖兞?#xff0c;如果要比較兩個(gè)變量是否指向同一個(gè)對象,即要看這兩個(gè)變量所對應(yīng)的內(nèi)存中的數(shù)值是否相等,這時(shí)候就需要用==操作符進(jìn)行比較。
equals方法是用于比較兩個(gè)獨(dú)立對象的內(nèi)容是否相同,就好比去比較兩個(gè)人的長相是否相同,它比較的兩個(gè)對象是獨(dú)立的。例如,對于下面的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句創(chuàng)建了兩個(gè)對象,然后用a/b這兩個(gè)變量分別指向了其中一個(gè)對象,這是兩個(gè)不同的對象,它們的首地址是不同的,即a和b中存儲(chǔ)的數(shù)值是不相同的,所以,表達(dá)式a==b將返回false,而這兩個(gè)對象中的內(nèi)容是相同的,所以,表達(dá)式a.equals(b)將返回true。
在實(shí)際開發(fā)中,我們經(jīng)常要比較傳遞進(jìn)行來的字符串內(nèi)容是否等,例如,String input = …;input.equals(“quit”),許多人稍不注意就使用==進(jìn)行比較了,這是錯(cuò)誤的,隨便從網(wǎng)上找?guī)讉€(gè)項(xiàng)目實(shí)戰(zhàn)的教學(xué)視頻看看,里面就有大量這樣的錯(cuò)誤。記住,字符串的比較基本上都是使用equals方法。
如果一個(gè)類沒有自己定義equals方法,那么它將繼承Object類的equals方法,Object類的equals方法的實(shí)現(xiàn)代碼如下:
boolean equals(Object o){
return this==o;
}
這說明,如果一個(gè)類沒有自己定義equals方法,它默認(rèn)的equals方法(從Object類繼承的)就是使用==操作符,也是在比較兩個(gè)變量指向的對象是否是同一對象,這時(shí)候使用equals和使用==會(huì)得到同樣的結(jié)果,如果比較的是兩個(gè)獨(dú)立的對象則總返回false。如果你編寫的類希望能夠比較該類創(chuàng)建的兩個(gè)實(shí)例對象的內(nèi)容是否相同,那么你必須覆蓋equals方法,由你自己寫代碼來決定在什么情況即可認(rèn)為兩個(gè)對象的內(nèi)容是相同的。
-----------------------------------------------------------------
簡單的說,==比較兩個(gè)人是否究竟是真正同一個(gè)人,equals一般用來比較兩個(gè)人在邏輯上是否相等(比如規(guī)定兩人成年之后身高相同就算兩人相同等等),想怎么定義就怎么定義,如果不覆蓋equals方法的話,默認(rèn)仍然是比較兩人是否同一個(gè)人(廢話,兩個(gè)人都還處于胚胎狀態(tài),都沒有具體特征,怎么可能在邏輯上比較)。
先說“==”:
“==”是用來比較兩個(gè)String對象在內(nèi)存中的存放地址是否相同的。例如,
| 1 2 3 4 5 6 7 8 9 | String test1 =?"test"; String test2 =?"test"; String test3 =?new?String(test2); String test4? =new?String(test2); blooean result1 = (test1==test2); blooean result2 = (test3==test4); |
其中:result1為true,result2為false。
原因:程序在運(yùn)行時(shí)有一個(gè)字符串緩存機(jī)制,當(dāng)String test1 = "test"的時(shí)候,程序先從緩存池中查找是否有相同的String 對象,如果有的話就不會(huì)重新生成而是用緩存池中的字符串對象;如果在字符串緩存池中沒找到相同的字符串對象時(shí)才會(huì)在內(nèi)存中開辟一塊內(nèi)存區(qū)新建字符串對象。對于test1,當(dāng)test1建立以后會(huì)將“test”字符串放入緩存池中,所以運(yùn)行 String test2 = "test"的時(shí)候就會(huì)直接從緩存池中取出相同的對象,也就說,test1和test2的內(nèi)存地址是相同的,所以,result1是true。對于new來說,每new一次就會(huì)在內(nèi)存中開辟一片內(nèi)存區(qū)域,test3和test4的內(nèi)存地址是不同的,所以result2是false。
再說“equal方法”:
equal方法是object類的方法,object類中的equal方法也使用“==”實(shí)現(xiàn)的,也就是說,如果直接繼承object類的equal方法,則也是比較兩個(gè)對象在內(nèi)存中的地址是否相同,但是在String中將繼承自object的equal方法覆蓋啦!String中的equal方法源碼如下:
1 /**2 * Compares this string to the specified object. The result is {@code3 * true} if and only if the argument is not {@code null} and is a {@code4 * String} object that represents the same sequence of characters as this5 * object.6 *7 * @param anObject8 * The object to compare this {@code String} against9 * 10 * @return {@code true} if the given object represents a {@code String} 11 * equivalent to this string, {@code false} otherwise 12 * 13 * @see #compareTo(String) 14 * @see #equalsIgnoreCase(String) 15 */ 16 public boolean equals(Object anObject) { 17 if (this == anObject) { 18 return true; 19 } 20 if (anObject instanceof String) { 21 String anotherString = (String) anObject; 22 int n = value.length; 23 if (n == anotherString.value.length) { 24 char v1[] = value; 25 char v2[] = anotherString.value; 26 int i = 0; 27 while (n-- != 0) { 28 if (v1[i] != v2[i]) 29 return false; 30 i++; 31 } 32 return true; 33 } 34 } 35 return false; 36 }可以看出:在String中的equal方法是比較兩個(gè)String對象的內(nèi)容是否相同。
?
java中的equals與==?
?
在初學(xué)Java時(shí),可能會(huì)經(jīng)常碰到下面的代碼:
1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2));為什么第4行和第5行的輸出結(jié)果不一樣?==和equals方法之間的區(qū)別是什么?如果在初學(xué)Java的時(shí)候這個(gè)問題不弄清楚,就會(huì)導(dǎo)致自己在以后編寫代碼時(shí)出現(xiàn)一些低級的錯(cuò)誤。今天就來一起了解一下==和equals方法的區(qū)別之處。
一.關(guān)系操作符“==”到底比較的是什么?
下面這個(gè)句話是摘自《Java編程思想》一書中的原話:
“關(guān)系操作符生成的是一個(gè)boolean結(jié)果,它們計(jì)算的是操作數(shù)的值之間的關(guān)系”。
這句話看似簡單,理解起來還是需要細(xì)細(xì)體會(huì)的。說的簡單點(diǎn),==就是用來比較值是否相等。下面先看幾個(gè)例子:
public class Main {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubint 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);}}輸出結(jié)果為 true false true
n==m結(jié)果為true,這個(gè)很容易理解,變量n和變量m存儲(chǔ)的值都為3,肯定是相等的。而為什么str1和str2兩次比較的結(jié)果不同?要理解這個(gè)其實(shí)只需要理解基本數(shù)據(jù)類型變量和非基本數(shù)據(jù)類型變量的區(qū)別。
在Java中游8種基本數(shù)據(jù)類型:
浮點(diǎn)型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte)?, long(8 byte)
字符型: char(2 byte)
布爾型: boolean(JVM規(guī)范沒有明確規(guī)定其所占的空間大小,僅規(guī)定其只能夠取字面值"true"和"false")
對于這8種基本數(shù)據(jù)類型的變量,變量直接存儲(chǔ)的是“值”,因此在用關(guān)系操作符==來進(jìn)行比較時(shí),比較的就是?“值” 本身。要注意浮點(diǎn)型和整型都是有符號類型的,而char是無符號類型的(char類型取值范圍為0~2^16-1).
也就是說比如:
int n=3;
int m=3;
變量n和變量m都是直接存儲(chǔ)的"3"這個(gè)數(shù)值,所以用==比較的時(shí)候結(jié)果是true。
而對于非基本數(shù)據(jù)類型的變量,在一些書籍中稱作為 引用類型的變量。比如上面的str1就是引用類型的變量,引用類型的變量存儲(chǔ)的并不是 “值”本身,而是于其關(guān)聯(lián)的對象在內(nèi)存中的地址。比如下面這行代碼:
String str1;
這句話聲明了一個(gè)引用類型的變量,此時(shí)它并沒有和任何對象關(guān)聯(lián)。
而 通過new String("hello")來產(chǎn)生一個(gè)對象(也稱作為類String的一個(gè)實(shí)例),并將這個(gè)對象和str1進(jìn)行綁定:
str1= new String("hello");
那么str1指向了一個(gè)對象(很多地方也把str1稱作為對象的引用),此時(shí)變量str1中存儲(chǔ)的是它指向的對象在內(nèi)存中的存儲(chǔ)地址,并不是“值”本身,也就是說并不是直接存儲(chǔ)的字符串"hello"。這里面的引用和C/C++中的指針很類似。
因此在用==對str1和str2進(jìn)行第一次比較時(shí),得到的結(jié)果是false。因此它們分別指向的是不同的對象,也就是說它們實(shí)際存儲(chǔ)的內(nèi)存地址不同。
而在第二次比較時(shí),都讓str1和str2指向了str指向的對象,那么得到的結(jié)果毫無疑問是true。
二.equals比較的又是什么?
equals方法是基類Object中的方法,因此對于所有的繼承于Object的類都會(huì)有該方法。為了更直觀地理解equals方法的作用,直接看Object類中equals方法的實(shí)現(xiàn)。
該類的源碼路徑為:C:\Program Files\Java\jdk1.6.0_14的src.zip 的java.lang路徑下的Object.java(視個(gè)人jdk安裝路徑而定)。
下面是Object類中equals方法的實(shí)現(xiàn):
很顯然,在Object類中,equals方法是用來比較兩個(gè)對象的引用是否相等,即是否指向同一個(gè)對象。
但是有些朋友又會(huì)有疑問了,為什么下面一段代碼的輸出結(jié)果是true?
public class Main {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubString str1 = new String("hello");String str2 = new String("hello");System.out.println(str1.equals(str2));} }要知道究竟,可以看一下String類的equals方法的具體實(shí)現(xiàn),同樣在該路徑下,String.java為String類的實(shí)現(xiàn)。
下面是String類中equals方法的具體實(shí)現(xiàn):
可以看出,String類對equals方法進(jìn)行了重寫,用來比較指向的字符串對象所存儲(chǔ)的字符串是否相等。
其他的一些類諸如Double,Date,Integer等,都對equals方法進(jìn)行了重寫用來比較指向的對象所存儲(chǔ)的內(nèi)容是否相等。
總結(jié)來說:
1)對于==,如果作用于基本數(shù)據(jù)類型的變量,則直接比較其存儲(chǔ)的 “值”是否相等;
如果作用于引用類型的變量,則比較的是所指向的對象的地址
2)對于equals方法,注意:equals方法不能作用于基本數(shù)據(jù)類型的變量
?
?
如果沒有對equals方法進(jìn)行重寫,則比較的是引用類型的變量所指向的對象的地址;
諸如String、Date等類對equals方法進(jìn)行了重寫的話,比較的是所指向的對象的內(nèi)容
轉(zhuǎn)載于:https://www.cnblogs.com/fengli9998/p/7260744.html
總結(jié)
以上是生活随笔為你收集整理的String中的“equal方法”和“==”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CentOs 7.2下ELK日志分析系统
- 下一篇: ceph学习笔记之七 数据平衡