String、StringBuffer和StringBuilder的区别
我们为什么要引入StringBuffer和StringBuilder?
String的局限性:
String不是基本数据类型,在创建的字符串属于对象,一种是new()创建对象,一种是创建String类对象的引用变量。
但是,String是被final修饰的,它的值是不可改变的,这导致每次对String字符串进行操作,都会生成新的String对象,然后再将指针指向新的String对象,这样不仅导致效率低下,还会浪费内存空间。
我们来看下String的部分源码:
/*
被final修饰的类不可被继承
被final修饰的方法不可被重写
被final修饰的变量不可变
*/
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
使用JDK1.0.2中的serialVersionUID实现互操作性
*/
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>
字符串实例根据<A href=“{@docRoot}/./platform/serialization/spec写入ObjectOutputStream/output.html“>对象序列化规范,第6.2节,“流元素”</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
初始化新创建的{@code String}对象,使其表示空字符序列。请注意,由于字符串是不可变的,因此不需要使用此构造函数。
*/
public String() {
this.value = "".value;
}
.....
}
我们先来看一段简单的代码:
String str = "gok";
System.out.println(str); //gok
str = str + "666";
System.out.println(str); //gok666
在JVM运行时,先创建个str赋值为"gok",在第三行中JVM创建个名也为str的对象,再把666和原来字符串连接的的值赋值给新的str对象,而原来的str会被gc回收机制回收,所以str的值并没有被更改。
我们能看到,str初始值为"gok",然后在字符串后面加上新的字符串,这个过程需要重新在内存中开辟空间,最终得到"gok666"这个字符串,小小的一个操作需要开辟三个空间,造成了大量地内存浪费,执行效率低下。
引入StringBuffer和StringBuilder
当要对字符串进行频繁修改时,需要使用StringBuffer和StringBuilder类,来提高效率。与String类不同的是,StringBuffer和StringBuilder可以对字符串进行多次修改,并且不会产生未使用对象。
三者继承结构
StringBuffer和StringBuilder的区别
StringBuffer和StringBuilder中的方法和功能是完全等价的,都继承AbstractStringBuilder类
StringBuffer的大部分方法都被synchronized关键字修饰,线程比较安全,而StringBuilder没有,可以被认为线程不安全
在单线程的程序下,StringBuilder效率较高,而StringBuffer每次都要加锁,效率相对较低
String、StringBuffer、StringBuilder效率的比较
@Test
public void testStr4() {
// String
long startString = System.nanoTime();
String str1 = new String();
for (int i = 0; i < 10000; i++) {
str1 += "666";
}
long endString = System.nanoTime();
System.out.println("String时间:" + (endString - startString)+