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

JAVA回顾巩固之String、StringBuilder、StringBuffer结合源码比较

2016-07-24 10:21 676 查看
今天回顾巩固了一下java的基础知识,那么String、StringBuilder、StringBuffer之间有什么区别呢?

尝试查看源码之后,有了一个清晰的认识。

首先大体说明,通常情况下大家都知道,String是不可变的字符串对象,StringBuilder、StringBuffer是可变的,其中StringBuilder线程不安全,StringBuffer线程安全,具体情况如下:

String:

源码注释写到:“Strings are constant; their values cannot be changed after they are created.“

具体到代码中:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];<pre name="code" class="java">    <span style="font-family: Arial, Helvetica, sans-serif;">…</span><span style="font-family: Arial, Helvetica, sans-serif;">…</span><pre name="code" class="java">}



看一看到,String其实就是一个char数组,但是由于使用了private修饰,且没有给出外部接口,又使用了final修饰,使得这个String对象一旦创建,就不能进行修改。

至于为什么可以对String进行赋值等操作,是因为对String进行赋值等操作以后,其实是给了String变量一个新的String对象,而之前被创建的对象依然存在于内存中。

StringBuilder和StringBuffer:

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence

从源码中可以看出StringBuilder和StringBuffer都继承于AbstractStringBuilder,实现的接口也是一致的。

再来看AbstractStringBuilder:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;

/**
* The count is the number of characters used.
*/
int count;
接口AbstractStringBuilder中,可以看到,StringBuilder和StringBuffer其实也是char数组,只不过没有用private和final进行修饰,这意味着他们是可变的。

其中最重要的一个方法就是append,同个这个方法,使得他们可以对数组进行扩容,我们都知道数组一旦被定义,那么长度就是一定的,不能再进行改变了,那他们是怎么做到对数组进行扩容的呢,于是查看了AbstractStringBuilder中以下源码:

void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow
throw new OutOfMemoryError();
newCapacity = Integer.MAX_VALUE;
}
value = Arrays.copyOf(value, newCapacity);
}


public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}


这里可以发现,其实并不是对原本的数组进行了修改,而是新建了一个数组,将原数组内容进行了copyOf操作,让value引用了新数组,旧的数组等待被回收。

而后通过观察发现,他们实现的方法也基本一致。

StringBuilder:

private StringBuilder append(StringBuilder sb) {
if (sb == null)
return append("null");
int len = sb.length();
int newcount = count + len;
if (newcount > value.length)
expandCapacity(newcount);
sb.getChars(0, len, value, count);
count = newcount;
return this;
}
    public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;
    }
StringBuffer:

public synchronized StringBuffer append(StringBuffer sb) {
super.append(sb);
return this;
}


这里可以看出唯一的区别是StringBuffer的方法基本上都有synchronized修饰,synchronized本意是同步的,java中用它来修饰一个方法或一块代码时,能保证同一时刻最多只有一个线程能执行改代码。所以有synchronized修饰即线程安全的。

比较的同时,通读了3个类中的源代码,发现了很多方法是以前不曾注意过的,但是都很有用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: