面試題:(多選)以下返回true的有()
A. "beijing" == "beijing"
B. "beijing".equals(new String("beijing"))
C. "beijing" == new String("beijing")
D. String a = "beijing";
String b = "beijing";
a == b
E. String a = new String("beijing")
String b = new String("beijing");
a == b
答案是 A,B,D
private void testSring() { if ("beijing" == "beijing") {
System.out.println("this is equal1"); } if ("beijing".equals(new String("beijing"))) { System.out.println("this is equal2"); } if ("beijing" == new String("beijing")) { System.out.println("this is equal3"); } String a = "beijing"; String b = "beijing"; if (a == b) { System.out.println("this is equal4"); } String m = new String("beijing"); String n = new String("beijing"); if (m == n) { System.out.println("this is equal5"); } }
執行結果為:
this is equal1
this is equal2
this is equal4
以下分析轉載自:http://blog.sina.com.cn/s/blog_6fd8a5870100qimb.html
Java中的String類是一種復合數據類型,比較String 類的是否相等也有2種辦法。"=="和equals()兩種。
String 是一個系統定義的類----不是基本數據類型,有關字符串處理的方法非常多,有時候兩個“一樣”的字符串做相等的比較運算時會得到true的結果,可是有的時候得到的結果卻是false,這是為什么呢?
要徹底的弄清這兩個字符串的相等比較,還得從系統的內存分配着手。
1 棧和堆的區別
棧和堆都是java 在ram中的數據存儲區,java自動管理棧和堆,程序員不能直接設置棧和堆。
1.1棧
棧的存取速度僅次於位於cpu中的寄存器,比堆的存取速度快,棧中數據項的插入和刪除,只能在棧頂的一端完成,棧的操作特性后進先出。棧中存放一些基本類型的變量和對象句柄,棧中的數據可以共享,缺點::存放在棧中的數據大小與生存期必須是確定的,缺乏靈活性,比如有如下例子:
int a = 3; int b = 3;
編譯器先處理int a = 3,首先它會在棧中創建一個整形變量為a的引用,然后在棧中查找有沒有值為3的存儲單元,如果沒有就開辟一個存放值為3的存儲單元,然后將a指向這個值為3的地址,接着處理int b = 3,在創建完變量b的引用后,由於棧中已經有了值為3的地址,這樣就出現了a和b同時指向3的情況。
假如再有a= 4,在編譯器內部它會重新搜索棧中是否有值為4的存儲單元,如果沒有,重新開辟地吃存放4的存儲單元;如果有則直接將a指向這個地址。因此a值的改變不會影響到b的值。
1.2堆
堆是一個運行時數據區,類的對象從中分配空間,通過如new等指令建立。堆的優點是可以動態的分配內存大小。生存期也不必事先告訴編譯器,java的垃圾收集器會自動回收不再使用的數據。但缺點是,由於要在運行時動態非配內存,存取速度比較慢。
2 字符串 “==”的比較
String是一個特殊的包裝類數據。當測試兩個包裝類的引用是否指向同一個對象時,用“==”。
String 類的對象有兩種形式創建:
形式1:String str = “abc”;
形式 2:String str = new String(“abc”) ;
2.1 兩者都為第一種形式創建的對象的比較
String str1 = “abc”;
String str2 = “abc”;
用語句String str1 = “abc”;創建對象java內部將此語句轉換為以下幾個步驟:
(1) 先定義一個名為str1 的對String類的對象引用變量。
(2) 在棧中查找有沒有存放值為“abc”的存儲單元,接着創建一個新的Sting類的對象0,並將對象0指向這個存儲單元,而且在棧中記下這個引用的對象0.如果已經有了值為“abc”的地址則查找對象0,並返回對象0的地址。
(3) 將str1指向對象0的地址。Str1指向存在棧中的數據的引用。
String str2 =”abc”;在棧中創建了一個對象引用str2.因為棧中已經有一個值為“abc”的對象0,因此jvm創建了兩個引用str1和str2,但只創建了一個對象,而且這兩個引用都指向了這個對象,所以這里str1 == str2.
2.2 同為第二種形式創建的兩個對象的比較
如:String str1 = new String(“abc”);
String str2 = new String(“abc”);
System.out.println(str1 ==str2);
系統在棧內存中分別創建了兩個對象引用變量str1和str2,同時在堆內存中創建了兩個對象。兩個引用變量分別表示兩個不同的對象,如圖所示,
無論堆內存中是否有相同的數據存在,也不會像棧中的數據共享。因此str1 != str2.
2.3兩種不同形式創建對象的比較
String str1 = new String(“abc”);
String str2 = “abc”;
System.out.println(str1 == str2); //false
Str1和str2是棧中創建的兩個引用,str1 指向了堆中的一個對象,而str2則指向了棧中的一個對象,即兩個引用分別指向不同的兩個對象,所以str1 != str2.
3 字符串值的比較
如果要比較兩個字符串的值就用equals()方法。如:str1.equals(str2)只要str1和str2的字面值相等結果就為true.
4 結論
(1) String str = “abc”;指向String類的引用被創建了。至於這個引用是否指向了一個新的對象,根據上下文來考慮。
(2) String str = new String(“abc”);在棧中創建了一個對象的引用srt,str指向在堆中創建的新對象。該對象值為“abc”的String類。
(3) 當比較包裝類里面的數值是否相等時,用equals方法,當測試兩個包裝類的引用是否指向一個對象的時候,用“==”。