标签:
面试的经历中,相信大家都经常被问到这三者的区别,说到String我相信绝大多数的人都会说:"String是不可变的,final修饰的",你会看到面试官微微猥琐一笑,接着问到:“final修饰的类就是不可变的吗,那StringBuilder和StringBuffer不是final修饰的?”
看下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对象,再通过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的部分源码
* @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则不是。
java面试题String,StringBuilder,StringBuffer
标签:
原文地址:http://blog.csdn.net/dfdsggdgg/article/details/51347748