String
打開String類的源碼是這樣的
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
.............
}
可以看到String是一個被final修飾的類(不要按類上的final,應該看value[]字段,String的文章中提到過String的底層是一個char的數組),而被final修飾後是無法修改繼承的(常量),所以其實你在更改String對象的值的時候並不是將他修改了,而是把當前對象附給新的對象然後JAVA虛擬機回收該對象
public class TestString {
public static void main(String[] args) {
String str="str";
//將str賦值給新的str然後回收之前的str對象
str=str+"a";
}
}
在操作大量字符串的時候難免會出現一個String對象的反覆新建與回收,所以當涉及大量字符串的修改時String會降低程序的效率
StringBuffer
StringBuffer與String不同他的char字段並沒有被final修飾,所以他本身是一個變量,所以在涉及大量字符串的修改時StringBuffer的效率比String更高,因爲他不需要在操作大量字符串時去反覆新建與回收對象。
當然在第一次聲明一個字符串時,看不出StringBuffer的優勢,因爲新建並沒有去改變String對象的值
public static void main(String[] args) {
String str="str";
StringBuffer stringBuffer=new StringBuffer("str");
}
StringBuilder
StringBuilder他的效率比StringBuffer更高,決定他效率更高的是他們的源碼中:StringBuilder中沒有鎖,而在StringBuffer中有大量的鎖(具體大家可以去看java源碼),所以StringBuilder同時也應該儘量避免在多線程下使用,而StringBuffer不需要在意這個問題
總結
String:適用與少量字符串的操作的情景;
StringBuffer:適用於多線程下大量字符串操作的情景;
StringBuilder:適用於多線程下大量字符串操作的情景;
具體效率差別大家可以去用代碼測試;