深入理解 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时,最好要考虑初始化一下缓冲大小,较少扩容的次数,提高效率。

参考文献:美团技术博客

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