源碼學習-String類

最近在掃描CodeDex時報了一個不能使用String.intern()的字符串來作鎖對象的告警,對這個問題有疑問查了些資料,順便學習一下String類的源碼。java

1.類定義 String 被final修飾,是葉子類,不能不繼承。實現了Serializable,Comparable,CharSequence 接口正則表達式

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {...}

Serializable:實現此接口來支持序列化和反序列化,Java的序列化機制是經過在運行時判斷類的serialVersionUID來驗證版本一致性的數組

Comparable:實現此接口的對象列表(和數組)能夠經過 Collections.sort (和 Arrays.sort )進行自動排序函數

CharSequence:字符序列,String本質是經過字符數組實現的學習

 

2.屬性ui

2.1 value final的數組,用來儲存String對象的字符this

2.2 hash String對象的HashCodespa

2.3 serialPersistentFields ?在序列化流協議中String類會被特別包裝,String對象會被寫入到一個ObjectOutputStream...code

3.構造方法orm

3.1 無參數構造方法默認返回空的字符串,由於String是不可變的,全部沒有必要使用此構造函數

1 public String() { 2 this.value = "".value; 3 }

3.2

1 public String(String original) { 2 this.value = original.value; 3 this.hash = original.hash; 4 }

3.3

1 public String(char value[]) { 2 this.value = Arrays.copyOf(value, value.length); 3 }

3.4

public String(byte bytes[]) {//用默認的charset進行decode this(bytes, 0, bytes.length); } public String(byte bytes[], int offset, int length) { checkBounds(bytes, offset, length); this.value = StringCoding.decode(bytes, offset, length); } public String(byte bytes[], int offset, int length, Charset charset) { if (charset == null) throw new NullPointerException("charset"); checkBounds(bytes, offset, length); this.value = StringCoding.decode(charset, bytes, offset, length); }

3.5 把此String對象的字符copy到dst數組,dst數組中從dstBegin的位置開始放置,此方法不進行任何邊界校驗

void getChars(char dst[], int dstBegin) { System.arraycopy(value, 0, dst, dstBegin, value.length); }

3.6 比較此對象從toffset位置的len長度字符數組是否和other對象的ooffset位置的len長度字符數組是同一個數組

/* *比較本對象從toffset位置開始的len長度的char數組是否和other對象的ooffset位置開始的len長度的char數組是同一個數組 */ public boolean regionMatches(int toffset, String other, int ooffset, int len) {...} /* *帶boolean參數的表示是否忽略大小寫 */ public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {...} /* *在equalsIgnoreCase方法中調用了帶boolean參數的regionMatches */ public boolean equalsIgnoreCase(String anotherString) { ... }

3.7 是否以特定的字符串開頭和結尾

public boolean startsWith(String prefix, int toffset) {...} public boolean endsWith(String suffix) {...}//endsWith調用的startsWith

3.8 indexOf系列

View Code

3.9

public String substring(int beginIndex) {...}

3.10 concat() 本對象以後鏈接字符串,返回新生成新的字符串

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); }

3.11 校驗字符串是否符合正則表達式

public boolean matches(String regex) {...}

3.12 delimiter作鏈接符鏈接字符串列表或數組

public static String join(CharSequence delimiter, CharSequence... elements) { Objects.requireNonNull(delimiter); Objects.requireNonNull(elements); // Number of elements not likely worth Arrays.stream overhead. StringJoiner joiner = new StringJoiner(delimiter); for (CharSequence cs: elements) { joiner.add(cs); } return joiner.toString(); }

e.g.

public static void main(String[] args) { List<String> names=new ArrayList<String>(); names.add("1"); names.add("2"); names.add("3"); System.out.println(String.join("-", names)); String[] arrStr=new String[]{"a","b","c"}; System.out.println(String.join("-", arrStr)); }

輸出:

3.13 去除字符串先後空格返回生成的新的子字符串

public String trim() {...}

3.14 格式化字符串

3.14.1 方法簽名

public static String format(String format, Object... args) {...}

3.14.2 轉換符

 

說    明 

示    例

%s

字符串類型

"mingrisoft"

%c

字符類型

'm'

%b

布爾類型

true

%d

整數類型(十進制)

99

%x

整數類型(十六進制)

FF

%o

整數類型(八進制)

77

%f

浮點類型

99.99

%a

十六進制浮點類型

FF.35AE

%e

指數類型

9.38e+5

%g

通用浮點類型(f和e類型中較短的)

 

%h

散列碼

 

%%

百分比類型

%n

換行符

 

%tx

日期與時間類型(x表明不一樣的日期與時間轉換符

3.14.3 e.g.

System.out.println(String.format("如今的時間是:%d-%d-%d %d:%d:%d",2011,1,2,15,29,30));

輸出結果:

3.15 valueOf

public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }

3.16 String類私有維護的String pool 初始化時是空的,當對象s調用intern方法時,若是pool中已存在與之equals爲true的t對象,那麼池中存在的t對象會被返回,不然新的String對象會被加入到pool中,而後返回這個String對象的引用。

此得出結論:只要s.equals(t),s.intern() == t.intern() 爲true

public native String intern();

當使用String s = "abc"方式建立字符串時,字符串會自動加入常量池,而當使用String s = new String("abc")方式建立時,只有調用了s.intern()方法纔會把s加入常量池

String pool default size:

7u40以前:1009,

7u40+ to 8:60013

java6的時候存在PermGen區,容易形成oom,java7以後改成存在Heap區

7u02以後能夠用-XX:StringTableSize=100003 設置JVM參數

(參考http://java-performance.info/string-intern-in-java-6-7-8/)

相關文章
相關標籤/搜索