String和StringBuilder、StringBuffer的区别
(原文地址:http://blog.csdn.net/dfdsggdgg/article/details/51347748)
一、String
看下JDK1.7 String成员变量的源码
-
/**
-
* @author Lee Boynton
-
* @author Arthur van Hoff
-
* @author Martin Buchholz
-
* @author Ulf Zibis
-
* @see java.lang.Object#toString()
-
* @see java.lang.StringBuffer
-
* @see java.lang.StringBuilder
-
* @see java.nio.charset.Charset
-
* @since JDK1.0
-
*/
-
-
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;
可以看到String定义的成员变量value和hash,其中value是个字节数组,而且是final修饰,这个才是String不可变的关键点;
JDK1.7 String的部分注解
-
The Java language provides special support for the string
-
* concatenation operator ( + ), and for conversion of
-
* other objects to strings. String concatenation is implemented
-
* through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
-
* class and its <code>append</code> method.
-
* String conversions are implemented through the method
-
* <code>toString</code>, defined by <code>Object</code> and
-
* inherited by all classes in Java. For additional information on
-
* string concatenation and conversion, see Gosling, Joy, and Steele,
-
* <i>The Java Language Specification</i>.
上面解释了:
java为String提供了特殊的支持,例如:String a="a"; String b="b" ;当执行String
c=a+b操作时,实际上是创建一个StringBuilder对象或者StringBuffer对象,再通过apend()进行拼接,最后调用toStirng()生成一个新的对象给c。
String提供修改内容的方法最终都是调用new String()。看下 String的部分注释
-
/**
-
* The <code>String</code> class represents character strings. All
-
* string literals in Java programs, such as <code>"abc"</code>, are
-
* implemented as instances of this class.
-
* <p>
-
* Strings are constant; their values cannot be changed after they
-
* are created. String buffers support mutable strings.
-
* Because String objects are immutable they can be shared. For example:
-
* <p><blockquote><pre>
-
* String str = "abc";
-
* </pre></blockquote><p>
-
* is equivalent to:
-
* <p><blockquote><pre>
-
* char data[] = {'a', 'b', 'c'};
-
* String str = new String(data);
-
* </pre></blockquote><p>
-
* Here are some more examples of how strings can be used:
这里定义了一个String str = "abc";相当于char data[] = {'a', 'b', 'c'};String str = new String(data);
再来看一个substring()方法的源码
-
/**
-
* Returns a new string that is a substring of this string. The
-
* substring begins at the specified <code>beginIndex</code> and
-
* extends to the character at index <code>endIndex - 1</code>.
-
* Thus the length of the substring is <code>endIndex-beginIndex</code>.
-
* <p>
-
* Examples:
-
* <blockquote><pre>
-
* "hamburger".substring(4, 8) returns "urge"
-
* "smiles".substring(1, 5) returns "mile"
-
* </pre></blockquote>
-
*
-
* @param beginIndex the beginning index, inclusive.
-
* @param endIndex the ending index, exclusive.
-
* @return the specified substring.
-
* @exception IndexOutOfBoundsException if the
-
* <code>beginIndex</code> is negative, or
-
* <code>endIndex</code> is larger than the length of
-
* this <code>String</code> object, or
-
* <code>beginIndex</code> is larger than
-
* <code>endIndex</code>.
-
*/
-
public String substring(int beginIndex, int endIndex) {
-
if (beginIndex < 0) {
-
throw new StringIndexOutOfBoundsException(beginIndex);
-
}
-
if (endIndex > value.length) {
-
throw new StringIndexOutOfBoundsException(endIndex);
-
}
-
int subLen = endIndex - beginIndex;
-
if (subLen < 0) {
-
throw new StringIndexOutOfBoundsException(subLen);
-
}
-
return ((beginIndex == 0) && (endIndex == value.length)) ? this
-
: new String(value, beginIndex, subLen);
-
}
看完这些,你可以清楚的知道定义一个变量str="hello world",则是在内存中分配一个对象new String("hello world"),当你修改str="hello nimei",变量重新指向内存中新分配的new String("hello nimei");原来内存中的new String("hello world")还在那里,没有改变,等待垃圾回收。、
难道真的没有办法修改new String("hello world")对象中的值而不重新在内存中重新new一次吗?让我们来看看一个例子。

原来通过反射可以修改String对象中的内容,反射太强大了。
二、StringBuffer和StringBuilder
StringBuffer的部分源码
-
* @author Arthur van Hoff
-
* @see java.lang.StringBuilder
-
* @see java.lang.String
-
* @since JDK1.0
-
*/
-
public final class StringBuffer
-
extends AbstractStringBuilder
-
implements java.io.Serializable, CharSequence
-
{
-
-
/** use serialVersionUID from JDK 1.0.2 for interoperability */
-
static final long serialVersionUID = 3388685877147921107L;
-
-
/**
-
* 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 <code>capacity</code>
-
* argument is less than <code>0</code>.
-
*/
-
public StringBuffer(int capacity) {
-
super(capacity);
-
}
-
-
/**
-
* Constructs a string buffer initialized to the contents of the
-
* specified string. The initial capacity of the string buffer is
-
* <code>16</code> plus the length of the string argument.
-
*
-
* @param str the initial contents of the buffer.
-
* @exception NullPointerException if <code>str</code> is <code>null</code>
-
*/
-
public StringBuffer(String str) {
-
super(str.length() + 16);
-
append(str);
-
}
StringBuilder的部分源码
-
* @author Michael McCloskey
-
* @see java.lang.StringBuffer
-
* @see java.lang.String
-
* @since 1.5
-
*/
-
public final class StringBuilder
-
extends AbstractStringBuilder
-
implements java.io.Serializable, CharSequence
-
{
-
-
/** use serialVersionUID for interoperability */
-
static final long serialVersionUID = 4383685877147921099L;
-
-
/**
-
* Constructs a string builder with no characters in it and an
-
* initial capacity of 16 characters.
-
*/
-
public StringBuilder() {
-
super(16);
-
}
-
-
/**
-
* Constructs a string builder with no characters in it and an
-
* initial capacity specified by the <code>capacity</code> argument.
-
*
-
* @param capacity the initial capacity.
-
* @throws NegativeArraySizeException if the <code>capacity</code>
-
* argument is less than <code>0</code>.
-
*/
-
public StringBuilder(int capacity) {
-
super(capacity);
-
}
-
-
/**
-
* Constructs a string builder initialized to the contents of the
-
* specified string. The initial capacity of the string builder is
-
* <code>16</code> plus the length of the string argument.
-
*
-
* @param str the initial contents of the buffer.
-
* @throws NullPointerException if <code>str</code> is <code>null</code>
-
*/
-
public StringBuilder(String str) {
-
super(str.length() + 16);
-
append(str);
-
}
StringBuffer和StringBuilder的这部分源码基本一样,构造函数初始化大小都为16,都是继承了AbstractStringBuilder。
看看AbstractStringBuilder定义成员变量的源码
-
/**
-
* A mutable sequence of characters.
-
* <p>
-
* Implements a modifiable string. At any point in time it contains some
-
* particular sequence of characters, but the length and content of the
-
* sequence can be changed through certain method calls.
-
*
-
* @author Michael McCloskey
-
* @author Martin Buchholz
-
* @author Ulf Zibis
-
* @since 1.5
-
*/
-
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;
-
-
/**
-
* 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中定义的变量value,是个字节数组,和String的成员变量value相比,String的value是final修饰的,所以StringBuffer和StringBuilde的内容可以变。
在对比下StingBuffer和StringBuilder的实现其他细节,以append()方法为例。
-
public synchronized StringBuffer append(String str) {
-
super.append(str);
-
return this;
-
}
-
public StringBuilder append(String str) {
-
super.append(str);
-
return this;
-
}
两者最大的区别是:StingBuffer所有的实现的方法都是sychronized修饰的,StringBuilder则不是。
三、String、StringBuffer和StringBuilder的总结
1、概念总结
1).String和StringBuffer、StringBuilder相比,String是不可变的,String的每次修改操作都是在内存中重新new一个对象出来,而StringBuffer、StringBuilder则不用,并且提供了一定的缓存功能,默认16个字节数组的大小,超过默认的数组长度时,则扩容为原来字节数组的长度*2+2。
2).StringBuffer和StringBuilder相比,StringBuffer是synchronized的,是线程安全的,而StringBuilder是非线程安全的,单线程情况下性能更好一点;使用StringBuffer和StringBuilder时,可以适当考虑下初始化大小,较少扩容的次数,提高代码的高效性。
2、使用场景总结
1).如果要操作少量的数据用 = String
2).单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
3).多线程操作字符串缓冲区 下操作大量数据 = StringBuffer