黑马程序员技术交流社区

标题: 【上海校区】关于String和StringBuilder字符串长度的源码分析 [打印本页]

作者: 小影姐姐    时间: 2018-4-9 16:57
标题: 【上海校区】关于String和StringBuilder字符串长度的源码分析
本帖最后由 上海分校-小影 于 2018-4-10 11:05 编辑

​           很多Java初学者不理解为什么String长度不可变,StringBuilder长度可变的原理,在这里我们一起来看一下.
1.String长度不可变
   ​        String的有一个成员变量char value[],String保存的字符就是保存在这里,下面是String部分构造方法:
[AppleScript] 纯文本查看 复制代码
` /** The value is used for character storage. */
private final char value[];
public String() {

    this.value = new char[0];
}

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}`
   其中char value[]是用final修饰的,所以String类是不可变的,即字符串常量,所以每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。
2. StringBuilder 源码解析
成员变量字节数组value初始化完成。
[AppleScript] 纯文本查看 复制代码
 [mw_shl_code=applescript,true]   public AbstractStringBuilder append(String str) {  
      if (str == null)  
          return appendNull();//注意如果为str为null,会拼接一个"null"字符串  
      int len = str.length();  
      ensureCapacityInternal(count + len);//判断容量是否足够,如不够先扩容,再copy到新扩容后的数组  
      str.getChars(0, len, value, count);//把str copy到 字符数组中  
      count += len;//重新计算字符数组总长度  
      return this;  
  }  

private void ensureCapacityInternal(int minimumCapacity) {  
      // overflow-conscious code  
      if (minimumCapacity - value.length > 0)  
          expandCapacity(minimumCapacity);//容量不够,进行扩容  
  }  

  void expandCapacity(int minimumCapacity) {  
      int newCapacity = value.length * 2 + 2;//扩容两倍 + 2  
      if (newCapacity - minimumCapacity < 0)  
          newCapacity = minimumCapacity;  
      if (newCapacity < 0) {//溢出处理  
          if (minimumCapacity < 0) // overflow  
              throw new OutOfMemoryError();  
          newCapacity = Integer.MAX_VALUE;  
      }  
      value = Arrays.copyOf(value, newCapacity); //把老数据复制到扩容后的新数组。  
  }  
[/mw_shl_code]
StringBuilder实际上就是把待拼接的字符串,放到自己的字符数组,如果字符数组的容量不够,需要进行扩容。具体操作是新创建一个字符数组(容量为老数组的2倍+2),再把老数组中的内容copy到新数组。这就是为什么在拼接大量字符串(拼接后超过长度16),最好采用指定容量的方式创建StringBuilder(或StringBuffer),防止拼接过程中不断扩容带来的性能消耗。


作者: 歪果仁    时间: 2018-4-11 15:19
厉害厉害




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2