String
- String類直接繼承自O(shè)bject,內(nèi)部包含一個char數(shù)組,用于存放字符數(shù)據(jù)
- String對象是不可變的,也就是說,一旦為一個String對象賦值,就不能改變該對象的值。查看源碼可知,String 類中任何一個看上去會修改 String 的方法實際上都會返回一個新的String對象,以表示經(jīng)修改以后的 String對象,而原始的 String對象并未發(fā)生變化,不過當需要修改的String對象實際上內(nèi)容不需要發(fā)生變化時,就會直接返回指向原對象的引用,而不會創(chuàng)建新對象,這可以節(jié)約存儲空間和減少不必要的開銷。
public class String {
public static void main(String[] args) {
String str1 = "apple ";
String str2 = str1.toUpperCase();
String str3 = str1.toLowerCase();
print(str1);
print(str2);
print(str3);
}
}
//Output:
apple
APPLE
apple
- 用于 Stirng 的 “+” 和 “+=” 是 Java中唯一被重載過的操作符,Java不允許程序員重載任何操作符。然而由于String的不可變性,使用這兩個操作符時雖然能帶來代碼書寫上的方便,但可能會有效率上的損失。
public class String1 {
String implict(char[] chars){
// 使用操作符 += 完成字符拼接
String str = "";
for (int i = 0; i < chars.length; i++) {
str += chars[i];
}
return str;
}
String explict(char[] chars){
// 使用 StringBuilder 完成字符拼接
StringBuilder sb = new StringBuilder(chars.length);
//預先指定StringBuilder的大小可以避免不必要的擴容操作
for (int i = 0; i < chars.length; ++i){
sb.append(chars[i]);
}
return sb.toString();
}
}
implict
explict
解析:String1 類中有兩個方法,implict()方法使用經(jīng)過重載的操作符 “+=” 完成字符的拼接工作,explict()方法使用StringBuilder完成字符拼接工作。下面兩個圖分別為這兩個方法生成的字節(jié)碼文件。從圖中可以看出:
- += 操作符最終也是通過創(chuàng)建StringBuilder對象,然后調(diào)用StringBuilder的append()方法實現(xiàn) String的拼接的;
- 使用 += 操作符的方法循環(huán)體內(nèi)部邏輯相較直接使用StringBuilder稍復雜;
- 通過使用 += 操作符隱式使用StringBuilder,其實例化過程發(fā)生在循環(huán)體內(nèi)部,因此每一次循環(huán)均會創(chuàng)建一個新的StringBuilder對象,而顯式使用StringBuilder的方法,實例化過程發(fā)生在循環(huán)體外部,所以相較而言,顯式使用StringBuilder的方法效率較高;
StringBuider VS StringBuffer
*** 相同點:兩者均繼承自AbstractStringBuilder,都提供相同的API(即方法相同),兩者均是可變類型字符串
*** 不同點:StringBuilder是JavaSE 5 引入的,主要用于替換StringBuffer; StringBuffer是線程安全的,幾乎所有的方法均加有同步鎖;StringBuilder不是線程安全的,所以效率要優(yōu)于StringBuffer