① 概念
String屬於引用數據類型,被final修飾,不可被繼承改變
② String的內存模型
String s = "abc";
在編譯期會檢查pool中是否有"abc"對象,如果有則返回pool中對象地址,否則在pool中創建"abc"對象並返回地址
String s = new String("abc");
同樣在編譯期會判斷pool中是否有"abc"對象,如果沒有會在pool中新建一個,然後copy一個副本到heap area 中
③ 關於常量池
- 理解常量池:類似一個JVM級別的緩存
- 位置:JDK1.7之前String Pool處於Method area,1.7開始移到了Heap中
- 原理:String Pool 底層是一個固定大小的Hashtable,默認長度爲1009(可通過JVM參數
-XX:StringTableSize=1009
來跟改),放入的String很多是會導致Hash衝突嚴重,從而導致鏈表過長,影響性能
④ 關於intern()
- intern作用:將字符串緩存到常量池
- 原理:如果常量池中存在當前字符串, 就會直接返回當前字符串. 如果常量池中沒有此字符串, 會將此字符串放入常量池中後, 再返回
- 注意:JDK1.7開始,StringPool移到Heap Area中調用intern不會再在String中創建新的對象,而是保存Heap中Object的引用
- intern使用:當新建的String對象達到一定數量,會在Heap,StringPool中創建很多對象佔用空間也隨之變大,此時使用Intern()緩存到StringPool可以減少大量對象佔用空間,但是值的注意的是,StringPool是有大小的當過多使用intern導致StringPool鏈表過長時反而會得不償失
⑤ String常用方法
- 字符串長度:
int length()
- 子串截取【含頭不含尾】:
String substring(int beginIndex, int endIndex) / String substring(int Index)
- 忽略大小比較:
boolean equalsIgnoreCase(String anotherString)
- 拼接字符串:
String concat(String str)
- 首次出現的位置:
int indexOf(int ch/String str, int fromIndex)
- 最後出現的位置[從後面開始遍歷]:
int lastIndexOf(int ch/String str, int fromIndex)
- 指定位置的字符:
char charAt(int index)
- 大小寫轉換:
String toLowerCase() / String toUpperCase()
- 替換:
String replace(char oldChar, char newChar) / String replaceFirst(String regex, String replacement) / String replaceAll(String regex, String replacement)
- 去空格:
trim()
- 匹配開始結束位置:
boolean statWith(String prefix) / boolean endWith(String suffix)
- 判斷是否包含:
boolean contains(String str)
- 字符串分解:
String[] split(String str)
- 其它基本類型轉String:
static String valueOf()
- String轉其他類型:
static xx parseXX(String str)
- 字典大小比較:
int compareToIgnore(String anotherString)
- 格式化:
String.format("a%sc%sd", b, d)
⑥ StringBuilder、StringBuffer
- StringBuilder,StringBuffer是可變的
- StringBuilder是非線程安全的,StringBuffer 是線程安全的
- StringBuilder默認緩衝16,即使是
new StringBuilder("test")
也會在字符串長度之外再另外緩衝16 - 擴容:當append的字符長度超過緩衝長度後,則擴容爲原來字節數組的長度*2+2,如若還不夠則直接擴容到當前必要最小長度
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
值的注意的是:在使用StringBuilder時,最好要考慮初始化一下緩衝大小,較少擴容的次數,提高效率。
參考文獻:美團技術博客