String 是 Java 语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的Immutable类,被声明为 final class ,所有属性也都是final的。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的String对象。由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明显影响。

StringBuffer 是为了解决拼接产生太多中间对象的问题而提供的一个类,我们可以用append或者add方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是StringBuilder。

StringBuilder 是Java 1.5中新增的类,在能力上和StringBuffer没有本质区别,但是它去掉了线程安全的部分,有效减小了性能开销,是绝大部分情况下进行字符串拼接的首选。

注意事项

为了实现修改字符序列的目标,StringBuffer和StringBuilder底层都是利用可修改的(char,JDK9以后是byte)数组,二者都继承了AbstractStringBuilder,里面包含了基本操作,它们的区别仅在于最终的实现方法是否加了synchronized关键字。

另外,这个内部数组应该创建多大的呢?如果太小,拼接的时候可能要重新创建足够大的数组;如果太大,又会浪费空间。目前的实现是,构建时初始字符串长度加16(这意味着,如果构建时没有初始字符串,那么初始长度就是16)。我们如果确定拼接会发生非常多次,而且大概是可预计的,那么就可以指定合适的大小,避免很多次扩容的性能开销。扩容会产生多重开销,因为要抛弃原有数组,创建新的(可以简单认为是倍数)数组,还要进行arraycopy操作。

过早优化是万恶之源,考虑可靠性、正确性和代码可读性才是大多数应用开发最重要的因素。