String和StringBuilder、StringBuffer的区别
(原文地址:http://blog.csdn.net/dfdsggdgg/article/details/51347748)
一、String
看下JDK1.7 String成员变量的源码
-
-
-
-
-
-
-
-
-
-
-
-
- public final class String
- implements java.io.Serializable, Comparable<String>, CharSequence {
-
- private final char value[];
-
-
- private int hash;
-
-
- 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()方法的源码
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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
- {
-
-
- static final long serialVersionUID = 3388685877147921107L;
-
-
-
-
-
- public StringBuffer() {
- super(16);
- }
-
-
-
-
-
-
-
-
-
- public StringBuffer(int capacity) {
- super(capacity);
- }
-
-
-
-
-
-
-
-
-
- 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
- {
-
-
- static final long serialVersionUID = 4383685877147921099L;
-
-
-
-
-
- public StringBuilder() {
- super(16);
- }
-
-
-
-
-
-
-
-
-
- public StringBuilder(int capacity) {
- super(capacity);
- }
-
-
-
-
-
-
-
-
-
- public StringBuilder(String str) {
- super(str.length() + 16);
- append(str);
- }
StringBuffer和StringBuilder的这部分源码基本一样,构造函数初始化大小都为16,都是继承了AbstractStringBuilder。
看看AbstractStringBuilder定义成员变量的源码
-
-
-
-
-
-
-
-
-
-
-
-
- abstract class AbstractStringBuilder implements Appendable, CharSequence {
-
-
-
- char[] value;
-
-
-
-
- int count;
-
-
-
-
- AbstractStringBuilder() {
- }
-
-
-
-
- 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