String与StringBuffer与StringBuilder的区别
1.可变性
String内部的value值是final修饰的,所以它是一个不可变的类,每一次修改String的值的时候,都会产生一个新的对象。
StringBuffer和StringBuilder是一个可变类,字符串的变更不会产生新的对象。
2.线程安全性
String是一个不可变的类,是线程安全的。
StringBuffer也是线程安全的,因为它的每个操作方法里面都用了Synchronized同步关键字。
StringBuilder它不是线程安全的。
所以在多线程环境下,对字符串进行操作,我应该使用StringBuffer。
3.性能方面
String是性能最低的,因为不可变,意味着做字符串拼接或者修改的时候,我们需要重新去创建新的对象以及分配内存。
StringBuffer要比String的性能更高一点,因为它的可变性,意味关字符串可以直接被修改。
StringBuilder性能最高,因为无锁。
4.存储方面
String存储在字符串常量池中。StringBuilder和StringBuffer存储在堆内存空间。
StringBuilder和StringBuffer都是AbstractStringBuilder抽象类的实现类。
源码
String
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class Test {
      public static void main(String[] args) {         String str1 = "a";         String str2 = new String("a");         String strTmp = "";         String str3 = "a" + strTmp;         System.out.println(str1.equals(str2));         System.out.println(str1.equals(str3));         System.out.println(str1 == str2);         System.out.println(str1 == str3);     }
  }
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
   | private final char value[];	 public String() {       this.value = "".value;   }
    public String(String original) {       this.value = original.value;       this.hash = original.hash;   }
    public String(char value[]) {       this.value = Arrays.copyOf(value, value.length);   }
    public String(char value[], int offset, int count) {       if (offset < 0) {           throw new StringIndexOutOfBoundsException(offset);       }       if (count <= 0) {           if (count < 0) {               throw new StringIndexOutOfBoundsException(count);           }           if (offset <= value.length) {               this.value = "".value;               return;           }       }              if (offset > value.length - count) {           throw new StringIndexOutOfBoundsException(offset + count);       }       this.value = Arrays.copyOfRange(value, offset, offset+count);   }
    public String(int[] codePoints, int offset, int count) {       if (offset < 0) {           throw new StringIndexOutOfBoundsException(offset);       }       if (count <= 0) {           if (count < 0) {               throw new StringIndexOutOfBoundsException(count);           }           if (offset <= codePoints.length) {               this.value = "".value;               return;           }       }              if (offset > codePoints.length - count) {           throw new StringIndexOutOfBoundsException(offset + count);       }
        final int end = offset + count;
               int n = count;       for (int i = offset; i < end; i++) {           int c = codePoints[i];           if (Character.isBmpCodePoint(c))               continue;           else if (Character.isValidCodePoint(c))               n++;           else throw new IllegalArgumentException(Integer.toString(c));       }
               final char[] v = new char[n];
        for (int i = offset, j = 0; i < end; i++, j++) {           int c = codePoints[i];           if (Character.isBmpCodePoint(c))               v[j] = (char)c;           else               Character.toSurrogates(c, v, j++);       }
        this.value = v;   }
 
  | 
 
可以看到内部变量value使用的是final修饰的。
1 2 3
   | this.value = Arrays.copyOf(value, value.length);
  this.value = Arrays.copyOfRange(value, offset, offset+count);
 
  | 
 
内部同样有
相当于新申请了一块内存空间。
StringBuilder
1 2 3
   | public StringBuilder() {     super(16); }
 
  | 
 
1 2 3
   | AbstractStringBuilder(int capacity) {     value = new char[capacity]; }
 
  | 
 
1 2 3 4 5
   | @Override public StringBuilder append(String str) {     super.append(str);     return this; }
 
  | 
 
1 2 3 4 5 6 7 8 9
   | public AbstractStringBuilder append(String str) {     if (str == null)         return appendNull();     int len = str.length();     ensureCapacityInternal(count + len);     str.getChars(0, len, value, count);     count += len;     return this; }
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12
   | public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {     if (srcBegin < 0) {         throw new StringIndexOutOfBoundsException(srcBegin);     }     if (srcEnd > value.length) {         throw new StringIndexOutOfBoundsException(srcEnd);     }     if (srcBegin > srcEnd) {         throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);     }     System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
 
  | 
 
发现这里没有使用新的char数组
StringBuffer
1 2 3 4 5 6
   | @Override public synchronized StringBuffer append(String str) {     toStringCache = null;     super.append(str);     return this; }
 
  | 
 
只是在方法上加了synchronized关键字。