1. 怎么理解 StringBuilder
和 StringBuffer
- 如果字符串修改操作比较频繁,应该采用
StringBuilder
和StringBuffer
- 这两个类的方法基本是完全一样的,它们的实现代码也几乎一样。唯一的不同就在于
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 本地接口(JNI)是 Java 提供的一种技术,用于在 Java 中调用非 Java 实现的代码
- 实际上,
insert()
方法中的用native
修饰的System.arraycopy()
方法使用 C++ 语言实现的。之所以用 C++ 语言实现是因为这个功能非常常用,而 C++ 的实现效率要远高于 Java
9. String
可以直接使用 +
、/
、+=
运算符的背后原理是什么
- 这是 Java 编译器提供的支持
- 背后,Java 编译器一般会生成
StringBuilder
,+
和+=
操作会转换为调用append()
方法
10. 既然直接使用 +
和 +=
就相当于使用 StringBuilder
和 append()
,那还有什么必要直接使用 StringBuilder
呢
- 在简单的情况下,确定没必要
- 在稍微复杂的情况下,Java 编译器可能没有那么智能,它可能会生成过多的
StringBuilder
,尤其是在有循环的情况下 - 所以,对于简单的情况,可以直接使用
String
的+
和+=
;对于复杂的情况,尤其是有循环的时候,应该直接使用StringBuilder