String 是字符串常量(线程安全);
StringBuffer(线程安全), StringBuilder(非线程安全) 是字符串变量。
String、StringBuilder、StringBuffer类定义
它们三个类都被final说明这三个都是不可变类。
StringBuilder、StringBuffer这两个类都继承了AbstractStringBuilder。1
2
3
4
5
6
7
8
9
10
11public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
String、StringBuilder、StringBuffer创建
String类中包含一个不可变的char数组用来存放字符串.
String在创建的时候有两种创建方式,一种是直接声明String a = “abc”;还有一种是通过new String(“abc”)来进行创建,第一种方式创建会到常量池中寻找对应的字符串如果有则直接取出,否则在常量池中创建一个新的字符串。 使用new关键字会同样也会直接执行常量池操作,执行完后会在堆中创建对象,并返回引用。
1 | String str1 = “abc”; |
1
2
3
4
5/** 这个value被用于存放char变量 */
private final char value[];
public String() {
this.value = "".value;
}
1 | String str1 = new String("A"+"B") ; 会创建多少个对象? |
StringBuilder和SpringBuffer都使用父类的构造函数进行初始化,1
2
3
4
5
6public StringBuilder() {
super(16);
}
public StringBuffer() {
super(16);
}
父类的构造方法,
可以看到和String类的区别是value类没有使用final类去修饰,所以在高并发下对value的操作是不安全的。1
2
3
4char[] value;
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
String、StringBuilder、StringBuffer的操作
String的添加操作只需要使用+号连接就行,但是在javac进行编译过后也是使用StringBuilder去进行连接操作的。
StringBuilder、StringBuffer则需要使用append方法进行操作。
StringBuilder、StringBuffer他们两的append方法区别就在于StringBuilder没有同步锁,而StringBuffer加了同步锁。
他们同时都是调用父类的方法进行实现。
父类的append类似于Arraylist的add,在超出一定容量之后都是要对value数组进行扩容1
2
3
4
5
6
7
8
9
10
11
public StringBuilder append(String str) {
super.append(str);
return this;
}
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
总结
大部分情况下效率StringBuilder > StringBuffer > String
StringBuilder 和 StringBuffer在创建字符串对其进行操作的适合都是使用的统一个对象,而String的value是不可变的数组所以每次需要构造String的适合都是需要new出一个对象,再把这个对象引用过去,效率会很低下。