深入理解 String

① 概念


String屬於引用數據類型,被final修飾,不可被繼承改變

② String的內存模型


String s = "abc";

在編譯期會檢查pool中是否有"abc"對象,如果有則返回pool中對象地址,否則在pool中創建"abc"對象並返回地址

String s = new String("abc");

同樣在編譯期會判斷pool中是否有"abc"對象,如果沒有會在pool中新建一個,然後copy一個副本到heap area 中

③ 關於常量池


  1. 理解常量池:類似一個JVM級別的緩存
  2. 位置:JDK1.7之前String Pool處於Method area,1.7開始移到了Heap中
  3. 原理:String Pool 底層是一個固定大小的Hashtable,默認長度爲1009(可通過JVM參數-XX:StringTableSize=1009來跟改),放入的String很多是會導致Hash衝突嚴重,從而導致鏈表過長,影響性能

④ 關於intern()


  1. intern作用:將字符串緩存到常量池
  2. 原理:如果常量池中存在當前字符串, 就會直接返回當前字符串. 如果常量池中沒有此字符串, 會將此字符串放入常量池中後, 再返回
  3. 注意:JDK1.7開始,StringPool移到Heap Area中調用intern不會再在String中創建新的對象,而是保存Heap中Object的引用
  4. intern使用:當新建的String對象達到一定數量,會在Heap,StringPool中創建很多對象佔用空間也隨之變大,此時使用Intern()緩存到StringPool可以減少大量對象佔用空間,但是值的注意的是,StringPool是有大小的當過多使用intern導致StringPool鏈表過長時反而會得不償失

詳情參見:美團技術博客-String#inern詳解

⑤ String常用方法


  1. 字符串長度:int length()
  2. 子串截取【含頭不含尾】:String substring(int beginIndex, int endIndex) / String substring(int Index)
  3. 忽略大小比較:boolean equalsIgnoreCase(String anotherString)
  4. 拼接字符串:String concat(String str)
  5. 首次出現的位置:int indexOf(int ch/String str, int fromIndex)
  6. 最後出現的位置[從後面開始遍歷]:int lastIndexOf(int ch/String str, int fromIndex)
  7. 指定位置的字符:char charAt(int index)
  8. 大小寫轉換:String toLowerCase() / String toUpperCase()
  9. 替換:String replace(char oldChar, char newChar) / String replaceFirst(String regex, String replacement) / String replaceAll(String regex, String replacement)
  10. 去空格:trim()
  11. 匹配開始結束位置:boolean statWith(String prefix) / boolean endWith(String suffix)
  12. 判斷是否包含:boolean contains(String str)
  13. 字符串分解:String[] split(String str)
  14. 其它基本類型轉String:static String valueOf()
  15. String轉其他類型:static xx parseXX(String str)
  16. 字典大小比較:int compareToIgnore(String anotherString)
  17. 格式化:String.format("a%sc%sd", b, d)

⑥ StringBuilder、StringBuffer


  1. StringBuilder,StringBuffer是可變的
  2. StringBuilder是非線程安全的,StringBuffer 是線程安全的
  3. StringBuilder默認緩衝16,即使是new StringBuilder("test")也會在字符串長度之外再另外緩衝16
  4. 擴容:當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時,最好要考慮初始化一下緩衝大小,較少擴容的次數,提高效率。

參考文獻:美團技術博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章