值類型是存儲在內(nèi)存中的堆棧(以后簡稱棧),而引用類型的變量在棧中僅僅是存儲引用類型變量的地址,而其本身則存儲在堆中。
==操作比較的是兩個(gè)變量的值是否相等,對于引用型變量表示的是兩個(gè)變量在堆中存儲的地址是否相同,即棧中的內(nèi)容是否相同。
equals操作表示的兩個(gè)變量是否是對同一個(gè)對象的引用,即堆中的內(nèi)容是否相同。
==比較的是2個(gè)對象的地址,而equals比較的是2個(gè)對象的內(nèi)容。顯然,當(dāng)equals為true時(shí),==不一定為true
String中的equals和==
1、public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; }}上面這段程序中,到底有幾個(gè)對象呢?來檢測一下吧,稍微改動一下程序public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = "Monday"; if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); }
}編譯并運(yùn)行程序,輸出:s1 == s2說明:s1 與 s2 引用同一個(gè) String 對象 -- "Monday"!
2.再稍微改動一下程序,會有更奇怪的發(fā)現(xiàn):public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); if (s1.equals(s2)) System.out.println("s1 equals s2"); else System.out.println("s1 not equals s2"); }}我們將 s2 用 new 操作符創(chuàng)建程序輸出:s1 != s2s1 equals s2說明:s1 s2分別引用了兩個(gè)"Monday"String對象
- 字符串緩沖池原來,程序在運(yùn)行的時(shí)候會創(chuàng)建一個(gè)字符串緩沖池當(dāng)使用 s2 = "Monday" 這樣的表達(dá)是創(chuàng)建字符串的時(shí)候,程序首先會在這個(gè)String緩沖池中尋找相同值的對象,在第一個(gè)程序中,s1先被放到了池中,所以在s2被創(chuàng)建的時(shí)候,程序找到了具有相同值的 s1將 s2 引用 s1 所引用的對象"Monday"第二段程序中,使用了 new 操作符,他明白的告訴程序:"我要一個(gè)新的!不要舊的!"于是一個(gè)新的"Monday"Sting對象被創(chuàng)建在內(nèi)存中。他們的值相同,但是位置不同,一個(gè)在池中游泳一個(gè)在岸邊休息。哎呀,真是資源浪費(fèi),明明是一樣的非要分開做什么呢?
4.再次更改程序:public class TestString { public static void main(String[] args) { String s1 = "Monday"; String s2 = new String("Monday"); s2 = s2.intern(); if (s1 == s2) System.out.println("s1 == s2"); else System.out.println("s1 != s2"); if (s1.equals(s2 www.gzlij.com)) System.out.println("s1 equals s2"); else System.out.println("s1 not equals s2"); }}這次加入:s2 = s2.intern();程序輸出:s1 == s2s1 equals s2原來,(java.lang.String的intern()方法 "abc".intern()方法的返回值還是字符串"abc",表面上看起來好像這個(gè)方法沒什么用處。但實(shí)際上,它做了個(gè)小動作: 檢查字符串池里是否存在"abc"這么一個(gè)字符串,如果存在,就返回池里的字符串;如果不存在,該方法會把"abc"添加到字符串池中,然后再返回它的引用。)更好的辦法:把所有的String都intern()到緩沖池去吧最好在用到new的時(shí)候就進(jìn)行這個(gè)操作String s2 = new String("Monday").intern();然后就可以用==比較兩個(gè)字符串的值了