Java String2

下面程序的運(yùn)行結(jié)果是什么?

String stra = "ABC";
String strb = new String("ABC");
System.out.println(stra == strb);    //1,false
System.out.println(stra.equals(strb));    //2,true

對于 1 和 2 中兩個都是顯式創(chuàng)建的新對象,使用 == 總是不等,String 的 equals 方法有被重寫為值判斷,所以 equals 是相等的。

String str1 = "123";
System.out.println("123" == str1.substring(0));    //3,true
System.out.println("23" == str1.substring(1));    //4,false

對于 3 和 4 中 str1 的 substring 方法實(shí)現(xiàn)里面有個 index == 0 的判斷,當(dāng) index 等于 0 就直接返回當(dāng)前對象,否則新 new 一個 sub 的對象返回,而 == 又是地址比較,所以結(jié)果如注釋。源碼如下:
屏幕快照 2018-06-11 上午8.17.53.png
String str5 = "NPM";
String str6 = "npm".toUpperCase();
System.out.println(str5 == str6);    //7,false
System.out.println(str5.equals(str6));    //8,true

toUpperCase 方法內(nèi)部創(chuàng)建了新字符串對象,可以簡單看下源碼:

public String toUpperCase(Locale var1) {
...
return new String(var15, 0, var3 + var4);
}
String str9 = "a1";
String str10 = "a" + 1;
System.out.println(str9 == str10);    //11,true

對于 11 來說當(dāng)兩個字符串常量連接時(相加)得到的新字符串依然是字符串常量且保存在常量池中只有一份。

String str11 = "ab";
String str12 = "b";
String str13 = "a" + str12;
System.out.println(str11 == str13);    //12,false

對于 12 來說當(dāng)字符串常量與 String 類型變量連接時得到的新字符串不再保存在常量池中,而是在堆中新建一個 String 對象來存放,很明顯常量池中要求的存放的是常量,有 String 類型變量當(dāng)然不能存在常量池中了。

String str14 = "ab";
final String str15 = "b";
String str16 = "a" + str15; 
System.out.println(str14 == str16);    //13,true

對于 13 來說此處是字符串常量與 String 類型常量連接,得到的新字符串依然保存在常量池中,因為對 final 變量的訪問在編譯期間都會直接被替代為真實(shí)的值。

private static String getBB() {   
    return "b";   
}
String str17 = "ab";   
final String str18 = getBB();   
String str19 = "a" + str18;   
System.out.println(str17 == str19);    //14,false

對于 14 來說 final String str18 = getBB() 其實(shí)與 final String str18 = new String(“b”) 是一樣的,也就是說 return “b” 會在堆中創(chuàng)建一個 String 對象保存 ”b”,雖然 str18 被定義成了 final,但不代表是常量,因為雖然將 str18 用 final 修飾了,但是由于其賦值是通過方法調(diào)用返回的,那么它的值只能在運(yùn)行期間確定,因此指向的不是同一個對象,所以可見看見并非定義為 final 的就保存在常量池中,很明顯此處 str18 常量引用的 String 對象保存在堆中,因為 getBB() 得到的 String 已經(jīng)保存在堆中了,final 的 String 引用并不會改變 String 已經(jīng)保存在堆中這個事實(shí);對于 str18 換成 final String str18 = new String("b"); 一樣會返回 false,原因同理。

String str20 = "ab";
String str21 = "a";   
String str22 = "b";   
String str23 = str21 + str22;   
System.out.println(str23 == str20);    //15,false
System.out.println(str23.intern() == str20);    //16,true
System.out.println(str23 == str20.intern());    //17,false
System.out.println(str23.intern() == str20.intern());    //18,true

對于 15 到 18 來說 str23 == str20 就是上面剛剛分析的,而對于調(diào)用 intern 方法如果字符串常量池中已經(jīng)包含一個等于此 String 對象的字符串(用 equals(Object) 方法確定)則返回字符串常量池中的字符串,否則將此 String 對象添加到字符串常量池中,并返回此 String 對象的引用,所以 str23.intern() == str20 實(shí)質(zhì)是常量比較返回 true,str23 == str20.intern() 中 str23 就是上面說的堆中新對象,相當(dāng)于一個新對象和一個常量比較,所以返回 false,str23.intern() == str20.intern() 就沒啥說的了,指定相等。

注釋 11 到 14 深刻的說明了我們在代碼中使用 String 時應(yīng)該留意的優(yōu)化技巧!特別說明 String 的 + 和 += 在編譯后實(shí)質(zhì)被自動優(yōu)化為了 StringBuilder 和 append 調(diào)用,其實(shí)在Java中是先構(gòu)建一個StringBuiler對象,然后使用append()方法拼接字符串最后調(diào)用toString()方法生成字符串。但是如果在循環(huán)等情況下調(diào)用 + 或者 += 就是在不停的 new StringBuilder 對象 append 了,這是及其浪費(fèi)的,應(yīng)該直接創(chuàng)建StringBuilder來實(shí)現(xiàn)。

通過這些題說明要想玩明白 Java String 對象的核心其實(shí)就是玩明白字符串的堆棧和常量池,虛擬機(jī)為每個被裝載的類型維護(hù)一個常量池,常量池就是該類型所用常量的一個有序集合,包括直接常量(String、Integer 和 Floating Point 常量)和對其他類型、字段和方法的符號引用,池中的數(shù)據(jù)項就像數(shù)組一樣是通過索引訪問的,由于常量池存儲了相應(yīng)類型所用到的所有類型、字段和方法的符號引用,所以它在 Java 程序的動態(tài)鏈接中起著核心的作用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 RTFSC (Read the fucking source code )才是生活中最重要的。我們天天就是要...
    二毛_coder閱讀 522評論 1 1
  • 注:都是在百度搜索整理的答案,如有侵權(quán)和錯誤,希告知更改。 一、哪些情況下的對象會被垃圾回收機(jī)制處理掉 ?當(dāng)對象對...
    Jenchar閱讀 3,309評論 3 2
  • 1.類加載子系統(tǒng)負(fù)責(zé)從文件系統(tǒng)或者網(wǎng)絡(luò)中加載class信息,加載的信息存放在一塊稱之為方法區(qū)的內(nèi)存空間。 2.方法...
    Y了個J閱讀 553評論 3 1
  • 我養(yǎng)過好多貓,貓是很酷的,她喜歡你的時候會黏著你,陪你玩,讓你逗她,讓你覺得她與你有著不可分離的羈絆,或許她那時候...
    繁意閱讀 171評論 0 0
  • 文/可可易希 昨夜夢里 我哭了 尋遍每個角落 都不見你的蹤影 你還在躲 還是不來我身邊 時間總是太快 一年又一年 ...
    可可易希閱讀 580評論 11 14

友情鏈接更多精彩內(nèi)容