String与StringBuffer,StringBuider的区别
1.简单地说,就是一个变量和常量的关系.StringBuffer对象的内容可以修改;而字符串对象一旦产生后就不可以被修改,重新赋值其实是两个对象
的StringBuffer的内部实现方式和字符串不同,StringBuffer的在进行字符串处理时,不生成新的对象,在内存使用上要优于串类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入,删除等操作,使用StringBuffer要更加适合一些。
我们从底层代码分析看到
string类
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
String类的底层代码是由字符数组实现的,并且定义为final类型,其值为常量,不可改变。
StringBuffer类是继承AbstratStringBuider抽象类,可以看到用来实现的字符数组没有定义为final,可以对字符串本身进行修改,而不产生新的对象。
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
/**
通过对底层代码的比较得知:String类是一个常量,赋值后不能被改变。
StringBuffer和StringBuider类是一个变量,赋值后可以进行修改。
拓展:当我们连接字符串时,通过StringBuffer类连接比String类连接资源开销小。
例:String s1=“ds”;
String s2=“kk”;
String s3=s1+s2;
因为String底层未不可变的字符串,所以会创建三个对象,都会占用内存,而这三个对象一直都未失去引用,所以jvm无法垃圾回收,造成内存资源的大量浪费,这在我们开发中是不推崇的,而StringBuilder 与StringBuffer则不存在这样的问题。
对StringBuffer类的底层代码分析,通过判断字符数组长度是否足够,从而创建一个新的数组用来封装数据,而原来的对象被放弃引用,等待垃圾回收,从而减少内存的浪费。
AbstractStringBuilder append(AbstractStringBuilder asb) {
if (asb == null)
return appendNull();
int len = asb.length();
ensureCapacityInternal(count + len);
asb.getChars(0, len, value, count);
count += len;
return this;`
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
2.执行区别
StringBuffer和StringBuider
StringBuffer底层代码
public synchronized int length() {
return count;
}
@Override
public synchronized int capacity() {
return value.length;
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
大都加了同步函数,每进入一次函数就会判断锁。
StringBuider类
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
未加同步锁,不需要判断锁资源。
①StringBuffer在多线程时是安全的,StringBuider只适合单一线程来运行。
②在多线程执行时,我们用StringBuffer。在单线程执行时,用StringBuider,因为不需要判断同步锁,执行效率更高。