参考: https://cloud.tencent.com/developer/article/1645883
String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了
StringBuffer与StringBuilder都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,是可变类。
从四个例子看 String和StringBuffer和StringBuilder的区别
String s1 = "aaa";
String s2 = "bbb" + "ccc";
String s3 = s1 + "bbb";
String s4 = new String("aaa")
首先我们来探讨一下,他们各自创建了几个对象??
String s1 = “aaa”;
按照Java的机制,字符串在创建对象时,会先在常量池找 这个字符串是否存在
如果不存在就创建一个丢进去,如果存在就直接取。
那么第一个例子显然创建了一个对象,当然如果常量池里面有“aaa”是不会被创建的。
String s2 = “bbb” + “ccc”;
编译器首先会对其进行优化 String s2 = "bbb" + "ccc"
会直接被优化为 bbbccc
。也就是直接创建了一个 bbbccc 对象。
String s3 = s1 + “bbb”;
s3 执行 + 操作会创建一个 StringBuilder
对象然后执行初始化。执行 + 号相当于是执行 new StringBuilder.append()
操作
String s3 = s1 + "bbb";
相当于
String s3 = new StringBuilder().append(s1).append("bbb").toString();
而"bbb"也不在常量池中,也会创建一个"bbb"对象
从StringBuffer对象到String对象,显然调用了toString()方法
我们来看下toString()的源码
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
再次生成了一个String对象
于是,这个操作总共生成了三个对象
String s4 = new String(“aaa”)
因为用了new ,肯定会在堆中创建一个对象,然后再看常量池有没有,有则不创建。所以会创建一个或两个对象。
StringBuffer 对象、StringBuilder 对象
代表一个可变的字符串序列,当一个 他们被创建以后,通过一系列方法可以实现字符串的拼接、截取等操作。一旦通过他们生成了最终想要的字符串后,就可以调用其toString
方法来生成一个新的字符串。
那他们两个有什么区别呢??
StringBuffer 是线程安全的,用于多线程通信。
StringBuilder 不是线程安全,但是运行速度更快,用于单线程。
StringBuffer 在字符串拼接上面直接使用 synchronized
关键字加锁,从而保证了线程安全性。除此之外,他们几乎一模一样!
总结
简而言之:
String可以看作常量。
StringBuilder和StringBuffer可以看成变量。
执行效率:StringBuilder最高,StringBuffer次之,String最低
一般而言,如果要操作的数量比较小,应优先使用String类;如果是在单线程下操作大量数据,应优先使用StringBuilder类;如果是在多线程下操作大量数据,应优先使用StringBuilder类。