String、StringBuffer、StringBuilder的区别以及字符串常量池

1、String

String是Java中基础且重要的类,被声明为final class,除了hash这个属性其他属性都声明为final,因为它的不可变性,所以如果拼接字符串时候会产生很多无用的中间对象,如果频繁的进行这样的操作对性能有所影响。

2、StringBuffer

StringBuffer就是为了解决大量拼接字符串时产生很多中间对象问题而提供的一个类,它提供了append和add方法,可以将字符串添加到已有序列的末尾或者指定位置,它的本质是一个线程安全的可修改的字符序列,把所有修改数据的方法都加上了synchronized 

3、StringBuilder

但是保证线程安全是有性能代价的。在很多情况下我们的字符串拼接操作不需要线程安全,这时候StringBuilfer登场了,StringBuilder是JDK1.5发布的,StringBuilder和 StringBuffer本质上没有什么区别,就是去掉了保证线程安全的那部分,减少了开销

 

StringBuilder和StringBuffer二者都继承了AbstractStringBuilder,底层都是利用可修改的char数组(JDK9以后是byte数组)。所以如果我们有大量的字符串拼接,如果能够预知大小的话最好在new StringBuffer或者new StringBuilder的时候设置好capacity,避免多次扩容的开销。因为扩容要抛弃原有数组,还有进行数组拷贝创建新的数组。

 

我们平常开发通常情况下少量的字符串拼接其实没太必要担心,例如

String str = ''aa''+''bb''+''cc'';

像这种没有变量的字符串,编译阶段就直接合成“aabbcc”了,然后看字符串常量池里有没有,有就直接引用,没有就在常量池中生成,返回引用。

如果是带变量的,影响也不大,JVM会帮我们优化。

4、字符串常量池

创建一个字符串时,首先会检查池中是否有值相同的字符串对象,如果有就直接返回引用,不会创建字符串对象;如果没有则新建字符串对象,返回对象引用,并且将新创建的对象放入池中。但是,通过new方法创建的String对象是不检查字符串常量池的,而是直接在堆中创建新对象,也不会把对象放入池中。

String str1 = “aaa”; // 检查字符串常量池

String str2 = new String(“aaa”);//不检查字符串常量池

总结:

1、在字符串不经常发生变化的业务场景优先使用String(代码更清晰简洁)。如常量的声明,少量字符串操作(拼接、删除等)。

2、在单线程情况下,如果有大量的字符串操作情况,应该使用StringBuilder来操作字符串。不能使用“+”来拼接,避免产生大量无用的中间对象,耗费空间而且执行效率低下(新建对象、回收对象花费大量时间)。如JSON的封装等。

3、在多线程情况下,如果有大量的字符串操作情况,应该使用StringBuffer。如HHTTP参数解析和封装等。

4、速度:StringBuilder > StringBuffer > String


版权声明:本文为qq_34746239原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>