光看不如手搓!
如果这是一个面试问题,那么大多数人可能会这么回答:String由final修饰是不可变的;StringBuffer是线程安全的;StringBuilder是线程不安全的。
那应用场景是什么?
String:
不可变的序列,运用在字符串不经常变化的方法中。String在Java中提供了+运算符来进行拼接。但这里有一个性能问题,String在JVM中其实是new的StringBuilder对象,利用append方法来处理的,对性能是有所影响的。
比如这段代码:
我们检查它的字节码发现它其实是new了2次StringBuiler,开辟新的内存空间:
StringBuilder:
StringBuilder的出现其实就是为了解决大量字符串通过String来拼接导致不停的开辟内存空间,降低内存的消耗。
比如这段代码:
为什么会给一个capacity的值呢?
因为StringBuilder是继承的AbstractStringBuilder。底层其实是一个char数组
数组在容量空间不足的情况下是需要扩容的。就是重新创建一个新的数组,然后将旧的数据copy过去。对性能是有一定的影响的,特别是我们在循环中用到String、StringBuilder,StringBuffer。而循环的次数是根据数据库数据或者其他不定参数来的。要小心使用。
来看看编译后的字节码:
只创建了一次。
StringBuffer:
StringBuffer用法和StringBuilder类似的。都是继承的AbstractStringBuilder,也会存在容量扩容的问题。但是StringBuffer是线程安全的。在并发编程中,涉及字符串的操作,应该注意使用StringBuffer。
我们可以看到,StringBuffer的方法是加了同步锁synchronized
总结一下:
String:在对字符串操作不是特别频繁下用String。String在定义的时候会去检查Java的常量池。比如String a ="bbb"。jvm会去检查常量池,这样就不会去创建新的对象了。
StringBuffer:对大量字符串进行操作,线程安全,在多线程场景下应该使用。
StringBuilder:对大量字符串进行操作,线程不安全,在单线程场景下应该使用。
注意事项:
1.我们在日常开发中,String是最常使用的。在我们针对循环的字符串拼接的时候,一定要注意,因为String在最终会被JVM优化成用StringBuilder。那么存在频繁的创建新的对象,导致资源浪费。
2.在使用StringBuilder和StringBuffer的时候,可以考虑给出容量具体的值,这样避免在循环拼接的时候,导致底层扩容,降低效率。
网友评论