在遇到字符串常量之間的拼接時,編譯器會作出優化,即在編譯期間就會完成字符串的拼接。所以,在使用==進行String對象之間的比較時,咱們須要特別注意java
//編譯器作了優化,直接在編譯的時候將字符串進行拼接 String str1 = "hello" + " java";//至關於str1 = "hello java"; String str2 = "hello java"; System.out.println(str1 == str2);//true String str3 = "hello"; String str4 = " java"; //編譯的時候不知道變量中存儲的是什麼,因此沒辦法在編譯的時候優化 String str5 = str3 + str4; System.out.println(str2 == str5);//false }
String使用的陷阱
String一經初始化後,就不會再改變其內容了。對String字符串的操做其實是對其副本(原始拷貝)的操做,原來的字符串一點都沒有改變。好比:
String s ="a"; 建立了一個字符串
s = s+"b"; 實際上原來的"a"字符串對象已經丟棄了,如今又產生了另外一個字符串s+"b"(也就是"ab")。 若是屢次執行這些改變串內容的操做,會致使大量副本字符串對象存留在內存中,下降效率。若是這樣的操做放到循環中,會極大影響程序的時間和空間性能,甚至會形成服務器的崩潰。
相反,StringBuilder和StringBuffer類是對原字符串自己操做的,能夠對字符串進行修改而不產生副本拷貝或者產生少許的副本。所以能夠在循環中使用。服務器
public class strspeed { public static void main(String[] args) { /**使用String進行字符串的拼接*/ String str0 = ""; //本質上使用StringBuilder拼接, 可是每次循環都會生成一個StringBuilder對象 long num1 = Runtime.getRuntime().freeMemory();//獲取系統剩餘內存空間 long time1 = System.currentTimeMillis();//獲取系統的當前時間 for (int i = 0; i < 10000; i++) { str0 = str0 + i;//至關於產生了10000個對象 } long num2 = Runtime.getRuntime().freeMemory(); long time2 = System.currentTimeMillis(); System.out.println("String佔用內存 : " + (num1 - num2)); System.out.println("String佔用時間 : " + (time2 - time1)); /**使用StringBuilder進行字符串的拼接*/ StringBuilder sb1 = new StringBuilder(""); long num3 = Runtime.getRuntime().freeMemory(); long time3 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { sb1.append(i); } long num4 = Runtime.getRuntime().freeMemory(); long time4 = System.currentTimeMillis(); System.out.println("StringBuilder佔用內存 : " + (num3 - num4)); System.out.println("StringBuilder佔用時間 : " + (time4 - time3)); } } /* String佔用內存 : 24643552 String佔用時間 : 134 StringBuilder佔用內存 : 0 StringBuilder佔用時間 : 1 */