第5讲 | String、StringBuffer、StringBuilder有什么区别?

典型回答

String是典型的Immutable类,被声明为 final class,所有属性都是final的。类似拼接、裁剪字符串等动作,都会产生新的 String 对象,相关操作的效率往往对应用性能有明显影响。

StringBuffer 是为解决操作String过程中产生太多中间对象问题而提供的类,本质是一个线程安全的可修改字符串。它保证了线程安全,也随之带来了额外的性能开销。

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

字符串设计和实现考量

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

构建时初始字符串长度加 16(如果没有初始字符串,则为16)。如果我们确定会频繁拼接,那么可以指定合适的大小,避免多次扩容的开销。

非静态的拼接逻辑在 JDK 8 中会自动被 javac 转换为StringBuilder操作,而在Java9中利用InvokeDynamic,将字符串拼接的优化与 javac生成的字节码解耦。

字符串缓存

String 在 Java 6 以后提供了intern()方法,提示 JVM 把相应字符串缓存起来,被缓存的字符串是存在所谓 PermGen 里,由于空间有限,且只能被FullGC清理,容易引发OOM,因此不推荐使用。

在后续版本中,这个缓存被放置在堆中,这样就极大避免了永久代占满的问题,PermGen在Java8中也被替换为MetaSpace.

显示默认字符串缓冲池的大小:

-XX:+PrintStringTableStatistics

手动调整大小(大部分情况下不需要)

-XX:StringTableSize=N

你可能感兴趣的:(第5讲 | String、StringBuffer、StringBuilder有什么区别?)