您的位置:首页 > 产品设计 > UI/UE

java基础知识—String、StringBuffer和StringBuilder

2015-07-18 14:06 806 查看
本博文主要是介绍一下String、StringBuffer和StringBuilder之间的区别和联系。

1、从类的定义看StringBuffer、StringBuilder、String的关系

首先来看一下源码中这几个类的定义如下:

//CharSequence定义
public interface CharSequence

//StringBuffer定义
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence

//StringBuilder定义
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence

//String定义
public final class String
implements
java.io.Serializable, Comparable<String>, CharSequence


注意:String、StringBuffer、StringBuilder都是final类型的,这意味着它们是不能被其它类继承的(我哥们去阿里面试的时候被问过)

由以上源码定义我们可以得到三者之间的关系图如下所示:

可以发现三者都实现了CharSequence接口,CharSequence其实也就是定义了字符串操作的接口,这个接口包含length(), charAt(int index),

subSequence(int start, int end)这几个API接口。而StringBuilder和StringBuffer都继承自AbstractStringBuilder类。

2、从构造函数到具体的字符串拼接操作看看String、StringBuffer、StringBuilder的区别

2.1String的构造函数

public String() {
this.offset = 0;
this.count = 0;
this.value = new char[0];
}

/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param  original
*         A {@code String}
*/
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;

if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself.  Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off + size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}

this.offset = 0;
this.count = size;
this.value = v;
}

/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param  value
*         The initial value of the string
*/
public String(char[] value) {
this.offset = 0;
this.count = value.length;
this.value = StringValue.from(value);
}
再看看String类中的contact()函数——将指定字符串联到此字符串的结尾。

public String concat(String str) {
int otherLen = str.length();

if (otherLen == 0) {
return this;
}

char[] buf = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);

return new String(0, count + otherLen, buf);
}
从Concat函数中,我们可以知道在对字符串使用concat操作后,具体的操作new出一个等同于两个字符串连接总长度的新的char数组,然后将两个字符串复制到新的char数组中,然后返回一个新的String对象。

2.2StringBuilder常见构造函数

public StringBuffer() {
super(16);
}

public StringBuffer(int capacity) {
super(capacity);
}
从StringBuilder的构造函数中,我们可以看见StringBuilder直接调用父类(AbstractStringBuilder)的构造函数,我们再看AbstractStringBuilder的构造函数。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
final static int[] sizeTable = {
9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999,
Integer.MAX_VALUE
};

/**
* The value is used for character storage.
*/
char[] value;

/**
* The count is the number of characters used.
*/
int count;

/**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}

/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
//其他的一些逻辑
}
从AbstractStringBuilder的构造函数中,我们可以看出StringBuilder中存储字符串其实用的是一个char数组,capacity其实就是指定这个char数组的大小。

下面我们再从StringBuilder中的append函数看看他具体是怎么做的(以 append(String str) 为例看看)。

public StringBuilder append(String str) {
super.append(str);
return this;
}
来看看AbstractStringBuilder类中的append()函数

/**
     *  value 用来存储字符串.
     */
    char value[];

    /** 
     * 有效字符串的数目.
     */
    int count;
public AbstractStringBuilder append(String str) {
        if (str == null) {
            str = "null";
        }

        int len = str.length();
        if (len == 0) {
            return this;
        }

/**
     *  判断原来用于存储字符串的values的字符串数组有没有足够的大小来存储将要新添加入StringBuilder的字符串。如果不够用,那么就调用expandCapacity(int minimumCapacity)让容量翻两倍
     */


int newCount = count + len;

if (newCount > value.length) {

expandCapacity(newCount);

}

//getChars将字符串复制到指定的位置

str.getChars(0, len, value, count);

count = newCount;

return this;

}


2.3 StringBuffer构造函数

/**
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuffer() {
super(16);
}

/**
* Constructs a string buffer with no characters in it and
* the specified initial capacity.
*
* @param      capacity  the initial capacity.
* @exception  NegativeArraySizeException  if the capacity
*               argument is less than 0.
*/
public StringBuffer(int capacity) {
super(capacity);
}
StringBuffer也是直接调用父类(AbstractStringBuilder)的构造函数(见上面)StringBuffer的append()函数

public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
还是调用父类的append函数,但是在这里有值得注意的地方,StringBuffer的append函数有一个synchronized标识符,也就是说StringBuffer中的append函数是线程安全的,通过继续查阅其他StringBuffer中的函数,我们也可以发现他们有synchronized标识符,这就不难理解为什么StringBuffer是线程安全的,但是很明显加上线程控制会拖慢程序运行的速度,所以如果不需要线程控制,那么最好就用StringBuilder。

3.比较下三者之间的区别

3.1StringBuffer和StringBuilder之间的区别和联系。

StringBuilder StringBuffer都是可变的字符序列。它们都继承于AbstractStringBuilder,实现了CharSequence接口;StringBuilder是非线程安全的,而StringBuffer是线程安全的,但是很明显加上线程控制会拖慢程序运行的速度,所以如果不需要线程控制,那么最好就用StringBuilder。

3.2 String和StringBuffer、StringBuilder之间的区别。

StringBuffer和StringBuilder对象的内容可以修改;而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象。StringBuffer(StringBuilder)的内部实现方式和String不同,StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。StringBuffer对象的append效率要高于String对象的"+"连接操作。

参考:

/article/4763105.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: