0%

String、StringBuffer、StringBuilder的区别

String 是字符串常量(线程安全);
StringBuffer(线程安全), StringBuilder(非线程安全) 是字符串变量。

String、StringBuilder、StringBuffer类定义

它们三个类都被final说明这三个都是不可变类。
StringBuilder、StringBuffer这两个类都继承了AbstractStringBuilder。

1
2
3
4
5
6
7
8
9
10
11
public 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
2
3
4
5
String str1 = “abc”;
String str2 = “abc”;
String str3 = “abc”;
String str4 = new String(“abc”);
String str5 = new String(“abc”);

image.png

1
2
3
4
5
/** 这个value被用于存放char变量 */
private final char value[];
public String() {
this.value = "".value;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String str1 = new String("A"+"B") ; 会创建多少个对象?
String str2 = new String("ABC") + "ABC" ; 会创建多少个对象?

str1:
字符串常量池:"A","B","AB" : 3个
堆:new String("AB") :1个
引用: str1 :1个
总共 : 5个

str2 :
字符串常量池:"ABC" : 1个
堆:new String("ABC") :1个
引用: str2 :1个
总共 : 3个

StringBuilder和SpringBuffer都使用父类的构造函数进行初始化,

1
2
3
4
5
6
public StringBuilder() {
super(16);
}
public StringBuffer() {
super(16);
}

父类的构造方法,
可以看到和String类的区别是value类没有使用final类去修饰,所以在高并发下对value的操作是不安全的。

1
2
3
4
char[] 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
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}

总结

大部分情况下效率StringBuilder > StringBuffer > String
StringBuilder 和 StringBuffer在创建字符串对其进行操作的适合都是使用的统一个对象,而String的value是不可变的数组所以每次需要构造String的适合都是需要new出一个对象,再把这个对象引用过去,效率会很低下。