public final class String implements java.io.Serializable, Comparable<String>, CharSequence { //存儲字符,final修飾 private final char value[]; //緩存hash code,默認0 private int hash; //序列號 private static final long serialVersionUID = -6849794470754667710L; //聲明可序列化字段 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; }
public String() { this.value = "".value; }
初始化新建立的對象,表示空字符串""。請注意,此構造函數是不須要使用的,由於字符串是不可變的.
String str = new String(); 本質上是建立了一個空的字符數組,str的長度爲0 html
public String(String original) { this.value = original.value; this.hash = original.hash; }
初始化新建立的對象,表示和參數同樣的字符串,換句話說是建立了和參數同樣的對象副本,除非須要顯示的聲明副本,不然該構造函數是不須要的,由於字符串是不可變的java
public String(StringBuffer buffer) { synchronized(buffer) { this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); } }
把StringBuffer的內容複製到String對象中,隨後修改StringBuffer對象的值,並不會影響String對象數組
public String(StringBuilder builder) { this.value = Arrays.copyOf(builder.getValue(), builder.length()); }
把StringBuilder的內容複製到String對象中,隨後修改StringBuilder的值,並不會影響String對象;
此構造函數是爲了把StringBuilder轉移到String對象,可是推薦使用StringBuilder的toString()方法,由於運行更快緩存
//返回字符串的長度 public int length() { return value.length; } //比較兩個String值是否相等 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } //生成hash code public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
這裏能夠看到equals方法的實現也是調用了==來比較對象是否相同,所以在討論equals和==區別的時候 要全面分析.安全
存儲字符的數組value[]是final修飾的,值不可更改.多線程
可變的字符序列,StringBuilder和StringBuffer都繼承了該類,要了解StringBuilder和StringBuffer首先先了解AbstractStringBuilder.app
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char[] value; /** * The count is the number of characters used. */ int count; }
char[] value: 存儲字符的數組
int count: 存儲的字符的數量ide
/** * 無參構造器,用於子類序列化 */ AbstractStringBuilder() { } /** * 指定字符數組容量 */ AbstractStringBuilder(int capacity) { value = new char[capacity]; }
/** * 返回字符的數量 */ @Override public int length() { return count; } /** * 返回當前可存儲字符的最大數量,即容量 */ public int capacity() { return value.length; } /** * 保證當前容量大於等於指定的最小數量minimumCapacity,會調用擴容方法 */ public void ensureCapacity(int minimumCapacity) { if (minimumCapacity > 0) ensureCapacityInternal(minimumCapacity); } /** * 擴容,只有minimumCapacity大於當前容量,纔會copy數組擴容 */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } } /** * 當前對象拼接字符串str * 若是參數爲null,那麼最終字符串爲"null",若是參數類型爲boolean,那麼返回的是"true"或"false" * 例1: "abc".append(null) = "abcnull" * 例2: "abc".append(false) = "abcfalse" */ 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; }
可變的字符序列,非線程安全,StringBuilder和StringBuffer的實現方法很類似,區別在因而否線程安全,在單線程的狀況下可以使用StringBuilder,由於它比StringBuffer運行更快.StringBuilder繼承了AbstractStringBuilder類.函數
繼承父類ui
/** * 默認容量16 */ public StringBuilder() { super(16); } /** * 指定初始容量 */ public StringBuilder(int capacity) { super(capacity); } /** * 把String字符串初始化到對象中,容量變爲str的長度+16 */ public StringBuilder(String str) { super(str.length() + 16); append(str); } /** * 把字符初始化到對象中,容量變爲字符的長度+16 */ public StringBuilder(CharSequence seq) { this(seq.length() + 16); append(seq); }
同父類
可變的字符序列,線程安全,StringBuffer繼承了AbstractStringBuilder類.
繼承父類,同時還有屬性toStringCache
這裏涉及到一個關鍵字transient,其做用是讓某些被修飾的成員屬性變量不被序列化,爲何不須要序列化呢?主要是由於這個變量可能爲null,也可能非空,不能準確的表明StringBuffer的屬性.因此沒有必要序列化,也節省了空間.
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{ /** * 最後一次調用toString返回值的緩存 * 當StringBuffer被修改時該緩存被清除 */ private transient char[] toStringCache; /** 序列號 */ static final long serialVersionUID = 3388685877147921107L; }
同StringBuilder
與StringBuilder方法基本相同,區別在於在StringBuilder的方法上加了synchronized鎖. 不一樣的地方還包括每一個修改對象的方法,好比append方法都會清除toStringCache緩存.
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; } @Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
- 在調用toString方法的時候,會先判斷緩存toStringCache是否存在,若是不存在,那麼把當前對象賦值給toStringCache,而後獲得toStringCache的字符串;若是toStringCache已經存在,那麼直接讀取緩存的字符串.
- toStringCache是否存在依賴於StringBuffer對象是否被修改,若是被修改了,那麼緩存被清空.
原文出處:https://www.cnblogs.com/iceblow/p/11159120.html