前言
看了一篇文章,大概是講面試中的java基礎的,有如題這麼個面試題。我又翻了一些文章看了下,然後去看原始碼。看一下原始碼大概能更加了解一些。
String
String類是final的,表示不可被繼承,不可變的。註釋上也有說明:
其中用一個char[]來儲存String的值。
private final char value[];
一旦賦值,就不可改變。看一下,操作string的原始碼,例如 substring,replace,concat 等方法,最終結果都是返回 new String(...). 也就是重新建立了一個String物件。
public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }
public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); }
public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this; }
StringBuffer 和 StringBuilder
它兩個都是繼承自 AbstractStringBuilder 抽象類,不同的是StringBuffer類都是帶有 synchronized 關鍵字的。也就是說,StringBuffer是執行緒安全的,而 StringBuilder不是。他們中的方法基本上呼叫 super的方法。也就是AbstractStringBuilder 裡實現的方法。
平時用的比較多的就是 append 方法。我們看一下程式碼實現:
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; }
private void ensureCapacityInternal(int minimumCapacity) { // 當append之後的長度大於當前value的長度的時候,需要重新生成一個char[]陣列。 if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } }
public static char[] copyOf(char[] original, int newLength) {
//重新建立一個char[]陣列 char[] copy = new char[newLength];
//將之前的值賦值到該陣列中 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
ensureCapacityInternal 方法中,將 value的值重新擴充套件比如 str.append("abc")。假如之前value的值為:{'h','e','l','l','o'},當呼叫 str.getChars方法之後,會將 abc 追加到value陣列後,value值就變成 :{'h','e','l','l','o','a','b','c'}
其實 getChars 方法只是做了一件事情 :System.arraycopy。
如圖:
執行完arraycopy之後
總結
String 不可變,StringBuffer和StringBuilder可變,但是StringBuilder非執行緒安全。可以根據他們不同的特性分情況使用。