常用基础类(三):剖析 StringBuilder

  1. 怎么理解 StringBuilderStringBuffer
    答:

    • 如果字符串修改操作比较频繁,应该采用 StringBuilderStringBuffer
    • 这两个类的方法基本是完全一样的,它们的实现代码也几乎一样。唯一的不同就在于 StringBuffer 类是线程安全的,而 StringBuilder 类不是
    • 线程安全是有成本的,影响性能,而字符串对象及操作大部分情况下不存在线程安全问题
  2. StringBuilder 的基本用法?
    答:

    • 通过 new 新建 StringBuilder 对象。
    • 通过 append() 方法添加字符串。
    • 通过 toString() 方法获取构建完成的字符串。
  3. StringBuilder 的实现原理?
    答:源码基于 Java 7

    • String 类似,StringBuilder 类内部也封装了一个字符数组 char[] value,与 String 不同的是,它不是 final 的,可以修改
    • 另外,与 String 不同,字符数组中不一定所有位置都已经被使用,它有一个实例变量 int count 表示数组中已经使用的字符个数。
    • StringBuilder 继承自 AbstractStringBuilder,它的默认构造方法是:public StringBuilder() {super(16);}
  4. StringBuilder 类的 append() 方法的实现原理?
    答:

    • 如果字符数组的长度小于需要的长度,则调用 void expandCapacity(int minimumCapacity) 方法进行扩展容量。
    • 扩展的逻辑是:分配一个足够长度的新数组,然后将原内容复制到这个新数组中,最后让内部的字符数组指向这个新数组。其中,newCapacity 的计算方法是:int newCapacity = value.length * 2 + 2;
  5. 为什么不能需要多少就分配多少?
    答:不能,因为那就跟 String 一样了,每 append 一次,都会进行一次内存分配,效率低下

  6. 这种扩展策略最后为什么要加 2?
    答:这是一种指数扩展策略加 2 的原因是在原长度为 0 时也可以一样工作

  7. 为什么要这样扩展?
    答:

    • 这是一种折中策略,一方面要减少内存分配的次数,另一方面要避免空间浪费
    • 在不知道最终需要多长的情况下,指数扩展是一种常见的策略,广泛应用于各种内存分配相关的计算机程序中。
  8. 怎样理解 native 关键字?
    答:

    • native 关键字是一个修饰符,表示它修饰的方法的实现是通过 Java 本地接口实现的
    • Java 本地接口是 Java 提供的一种技术,用于在 Java 中调用非 Java 实现的代码
    • 实际上,insert() 方法中的用 native 修饰的 System.arraycopy() 方法使用 C++语言实现的。之所以用 C++ 语言实现是因为这个功能非常常用,而 C++ 的实现效率要远高于 Java
  9. String 可以直接使用 + / += 运算符的背后原理是什么?
    答:

    • 这是 Java 编译器提供的支持
    • 背后,Java 编译器一般会生成 StringBuilder+ 和 += 操作会转换为调用 append() 方法
  10. 既然直接使用 + 和 += 就相当于使用 StringBuilderappend(),那还有什么必要直接使用 StringBuilder 呢?
    答:

    • 在简单的情况下,确定没必要。
    • 在稍微复杂的情况下,Java 编译器可能没有那么智能,它可能会生成过多的 StringBuilder,尤其是在有循环的情况下。
    • 所以,对于简单的情况,可以直接使用 String+ 和 +=;对于复杂的情况,尤其是有循环的时候,应该直接使用 StringBuilder
    • 一切都是为了效率。