首先,String是不可变长的,当然也是线程安全的了(因为不可变长)。
String在String str = "艾弗森";
str = str + "乔丹";
这种情况的时候,堆内存里面会有一个“艾弗森”字符串和“艾弗森乔丹”字符串,str是指向“艾弗森乔丹”,而“艾弗森”是没有被任何变量引用的。也就造成了内存泄露。
其次,StringBuilder和StringBuffer都是可变长的,但StringBuffer是线程安全的,也就是多线程操作的时候它不会发生混乱,可以正常工作,因为它有锁那样的机制,增加了synchronized修饰符。StringBuder则是单线程安全的,只能单线程使用,多线程操作会不安全,但不用到多线程的时候StringBuder效率是三者最高的,因为StringBuffer的锁机制会消耗一定的效率。
StringBuffer str = "艾弗森";
str.append("乔丹");
StringBuder str1 = "樱木花道";
str1.append("流川枫");
这两个不会造成内存泄露。
append()函数对于各种参数类型和各种情况下的具体操作,在Java里面的定义如下:
public AbstractStringBuilder append(Object obj) { //AbstractStringBuilder是StringBuffer和StringBuilder的父类 return append(String.valueOf(obj)); } public AbstractStringBuilder append(String str) { if (str == null) str = "null"; int len = str.length();//=16 ensureCapacityInternal(count + len); str.getChars(0, len, value, count);//count的默认值都是16 count += len;//String.size()+16 return this; } // Documentation in subclasses because of synchro difference public AbstractStringBuilder append(StringBuffer sb) { if (sb == null) return append("null"); int len = sb.length(); ensureCapacityInternal(count + len); sb.getChars(0, len, value, count); count += len; return this; } // Documentation in subclasses because of synchro difference public AbstractStringBuilder append(CharSequence s) { if (s == null) s = "null"; if (s instanceof String) return this.append((String)s); if (s instanceof StringBuffer) return this.append((StringBuffer)s); return this.append(s, 0, s.length()); } public AbstractStringBuilder append(CharSequence s, int start, int end) { if (s == null) s = "null"; if ((start < 0) || (start > end) || (end > s.length())) throw new IndexOutOfBoundsException( "start " + start + ", end " + end + ", s.length() " + s.length()); int len = end - start; ensureCapacityInternal(count + len); for (int i = start, j = count; i < end; i++, j++) value[j] = s.charAt(i); count += len; return this; } public AbstractStringBuilder append(char[] str) { int len = str.length; ensureCapacityInternal(count + len); System.arraycopy(str, 0, value, count, len); count += len; return this; } public AbstractStringBuilder append(char str[], int offset, int len) { if (len > 0) // let arraycopy report AIOOBE for len < 0 ensureCapacityInternal(count + len); System.arraycopy(str, offset, value, count, len); count += len; return this; } public AbstractStringBuilder append(boolean b) { if (b) { ensureCapacityInternal(count + 4); value[count++] = 't'; value[count++] = 'r'; value[count++] = 'u'; value[count++] = 'e'; } else { ensureCapacityInternal(count + 5); value[count++] = 'f'; value[count++] = 'a'; value[count++] = 'l'; value[count++] = 's'; value[count++] = 'e'; } return this; } public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); value[count++] = c; return this; } public AbstractStringBuilder append(int i) { if (i == Integer.MIN_VALUE) { append("-2147483648"); return this; } int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1 : Integer.stringSize(i); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); Integer.getChars(i, spaceNeeded, value); count = spaceNeeded; return this; } public AbstractStringBuilder append(long l) { if (l == Long.MIN_VALUE) { append("-9223372036854775808"); return this; } int appendedLength = (l < 0) ? Long.stringSize(-l) + 1 : Long.stringSize(l); int spaceNeeded = count + appendedLength; ensureCapacityInternal(spaceNeeded); Long.getChars(l, spaceNeeded, value); count = spaceNeeded; return this; } public AbstractStringBuilder append(float f) { new FloatingDecimal(f).appendTo(this); return this; } public AbstractStringBuilder append(double d) { new FloatingDecimal(d).appendTo(this); return this; }