1. 程式人生 > >基礎 | String、StringBuffer與StringBuilder

基礎 | String、StringBuffer與StringBuilder

String類作為Java中的常用類,是各大公司面試時非常喜歡問到的地方,主要是String類夠基礎,但基礎中又會延伸出很多相關技術點,比如final關鍵字、Java記憶體分配、Java虛擬機器、執行緒安全等。

今天就主要分析一下 「String、StringBuffer和StringBuilder類以及三者之間的聯絡與區別」,需要重點關注,如有問題也可留言交流。


你瞭解String類嗎?

問題分析:該問題比較籠統,建議從修飾符、底層原理、常用方法和主要特性方面進行回答。

參考答案:

  • 修飾符:String類是final的,即意味著其不能被繼承,並且String類的成員方法都預設為final的。
  • 底層原理:String類是採用char型陣列來儲存字串的,可參看原始碼:private final char value[];
  • 常用方法:substring()、concat()、replace()等需要改變字串的操作都不是在原有字串上進行的,均需要重新生成新的字串物件。
  • 主要特性: 對String物件的任何改變都不影響原物件,因為其一經建立即不可變,相關的任何change操作都會生成新的物件。

String、StringBuffer與StringBuilder有什麼區別?

問題分析:先來了解一下Java虛擬機器對「string +=“hello”」的優化,優化結果為:

StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();

這是因為StringBuilder類表示可變的字元序列,其效率比String類高很多。

而StringBuilder和StringBuffer類擁有的成員屬性以及成員方法基本相同,區別是StringBuffer的成員方法被synchronized修飾,故StringBuffer類也表示可變的字元序列,但其是執行緒安全的,而StringBuilder類是執行緒不安全的。

參考答案:

  • 執行緒安全,只有StringBuffer類是執行緒安全的,String類和StringBuffer類都是執行緒不安全的。
  • 執行效率:通常情況下,StringBuilder > StringBuffer > String,但也有特例,具體如下:
String str = "hello"+ "world"; // 效率高,編譯器會對其字串的直接相加操作進行優化
StringBuilder st  = new StringBuilder().append("hello").append("world");

優化策略如下:

  • 直接相加:形如"I"+“love”+“java"的字串相加操作,在編譯期間即會被優化成"Ilovejava”,可以用javap -c命令反編譯生成的class檔案進行驗證。
  • 間接相加:即包含字串引用的相加操作,形如s1+s2+s3,效率要比直接相加低,因為編譯器不會對引用變數進行優化。

擴充套件面試題

問:String str = new String(“java”)建立了多少個物件?

答:準確來說,在類載入的過程中,該段程式碼在執行時常量池中建立了一個"java"物件,而在程式碼執行過程中在堆空間建立了一個String物件。故該段程式碼在執行期間僅建立了一個物件,但該段程式碼涉及到了兩個String物件。

擴充套件:關於String類的筆試題(重點關注)

public static void main(String[] args) {
	String stra = "hello2";
	String strb = "hello" + 2; //在編譯期間已被優化成"hello2"
	System.out.println(stra == strb); //true
	
	String strc = "hello2";
	String strd = "hello"; 
	String stre = strb + 2; //字串引用不會在編譯期間被優化
	System.out.println(strc == stre); //false
	
	String strf = "hello2";
	final String strg = "hello"; //final修飾的變數編譯時會在常量池儲存一個副本
	String strh = strg + 2; //對final變數的訪問在編譯期間都會直接被替代為真實的值
	System.out.println(strf == strh); //true
	
	String stri = "hello2";
	final String strj = getHello(); //值是執行期間才確定的
	String strk = strj + 2; 
	System.out.println(stri == strk); //false
}

public static String getHello() {
    return "hello";
}

推薦閱讀


歡迎關注

Java名企面試吧,每天10點24分,我們不見不散!

丙子先生的宗旨是,每天以短篇幅講高頻面試題,不增加太多負擔,但需要持之以恆。

能力有限,歡迎指教!