详解String、StringBuffer和StringBuilder的区别和应用场景

时间:2023-01-15 08:14:57

    String、StringBuffer和StringBuilder的区别

     String:字符串常量 。StringBuffer 与 StringBuilder是字符缓冲变量。StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是StringBuffer中的方法大都采用了synchronized 关键字进行修饰,因此是线程安全的,而StringBuilder没有这个修饰,可以被认为是线程不安全的。StringBuilder 是在JDK1.5才加入的。jdk的实现中StringBuffer与StringBuilder都继承自AbstractStringBuilder。

     注意从JDK1.5开始,带有字符串变量的连接操作(+),JVM 内部采用的是 StringBuilder 来实现的,而之前这个操作是采用 StringBuffer 实现的。      1、String类型的字符串对象是不可变的,一旦String对象创建后,包含在这个对象中的字符系列是不可以改变的,直到这个对象被销毁。
     2、StringBuilder和StringBuffer类型的字符串是可变的,不同的是StringBuffer类型的是线程安全的,而StringBuilder不是线程安全的
     3、如果是多线程环境下涉及到共享变量的插入和删除操作,StringBuffer则是首选。如果是非多线程操作并且有大量的字符串拼接,插入,删除操作则StringBuilder是首选。毕竟String类是通过创建临时变量来实现字符串拼接的,耗内存还效率不高,怎么说StringBuilder是通过JNI方式实现终极操作的。
     4、StringBuilder和StringBuffer的“可变”特性总结如下:
         (1)append,insert,delete方法最根本上都是调用System.arraycopy()这个方法来达到目的
         (2)substring(int, int)方法是通过重新new String(value, start, end - start)的方式来达到目的。因此,在执行substring操作时,StringBuilder和String基本上没什么区别。
     总的来说,三者在执行速度方面的比较:StringBuilder > StringBuffer > String。  
String s = "abcd";
s = s+"ab";
System.out.print(s);// result : abcdab
   JVM执行上边的代码的时候,第一行代码在栈创建了一个s对象引用指向在堆区创建的字符对象"abcd",在执行第二行代码时候,会在堆区再创建一个字符对象"abcdab",s的引用指向了这个新创建的对象实例。原来的字符对象依然存在,所以说它不能改变。在堆区的无用的字符对象会等待JVM的GC,所以其执行速度会很慢。

    一个特殊的例子

String str = "This is only a" + "simple" + "test";
StringBuffer builder = new StringBuilder("This is only a").append("simple").append("test");
   上边的例子会发现str的生成速度很快,这其实是JVM把戏。
String str = "This is only a" + "simple" + "test";
    其实就是:
String str = "This is only a simple test"
    所以不需要太多的时间了。但如果你的字符串是来自另外的String对象的话,JVM就会像上边一样执行了。

   StringBuffer和StringBuilder的区别

   jdk的实现中StringBuffer与StringBuilder都继承自AbstractStringBuilder。AbstractStringBuilder的实现原理:我们知道使用StringBuffer等无非就是为了提高java中字符串连接的效率,因为直接使用+进行字符串连接的话,jvm会创建多个String对象,因此造成一定的开销。AbstractStringBuilder中采用一个char数组来保存需要append的字符串,char数组有一个初始大小(16),当append的字符串长度超过当前char数组容量时,则对char数组进行动态扩展,也即重新申请一段更大的内存空间,然后将当前char数组拷贝到新的位置,因为重新分配内存并拷贝的开销比较大,所以每次重新申请内存空间都是采用申请大于当前需要的内存空间的方式,这里是2倍。