首页 > 编程 > Java > 正文

java面试题String,StringBuilder,StringBuffer

2019-11-08 01:58:20
字体:
来源:转载
供稿:网友
     面试的经历中,相信大家都经常被问到这三者的区别,说到String我相信绝大多数的人都会说:"String是不可变的,final修饰的",你会看到面试官微微猥琐一笑,接着问到:“final修饰的类就是不可变的吗,那StringBuilder和StringBuffer不是final修饰的?”

1. 先来说说String

看下JDK1.7 String成员变量的源码

[java] view plain copy 在CODE上查看代码片/**  * @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%20String的部分注解

[java]%20view%20plain%20copy%20The 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%20a="a";%20 String%20b="b"%20;当执行String%20c=a+b操作时,实际上是创建一个StringBuilder对象,再通过apend()进行拼接,最后调用toStirng()生成一个新的对象给c。

String提供修改内容的方法最终都是调用new%20String()。看下 String的部分注解

[java]%20view%20plain%20copy%20/**   * 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%20str%20=%20"abc";相当于char%20data[]%20=%20{'a',%20'b',%20'c'};String%20str%20=%20new%20String(data);再来看一个substring()方法的源码

[java]%20view%20plain%20copy%20/**      * 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%20world",则是在内存中分配一个对象new%20String("hello%20world"),当你修改str="hello%20nimei",变量重新指向内存中新分配的new%20String("hello%20nimei");原来内存中的new%20String("hello%20world")还在那里,没有改变,等待垃圾回收。难道真的没有办法修改new%20String("hello%20world")对象中的值而不重新在内存中重新new一次吗?让我们来看看一个例子。

原来通过反射可以修改String对象中的内容,反射太强大了。

2.StringBuffer和StringBuilder

StringBuffer的部分源码

[java] view plain copy 在CODE上查看代码片* @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的部分源码

[java]%20view%20plain%20copy%20* @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定义成员变量的源码

[java]%20view%20plain%20copy%20/**  * 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()方法为例。

[java]%20view%20plain%20copy%20public synchronized StringBuffer append(String str) {         super.append(str);         return this;     }  [java]%20view%20plain%20copy%20派生到我的代码片public StringBuilder append(String str) {        super.append(str);        return this;    }  两者最大的区别是:StingBuffer所有的实现的方法都是sychronized修饰的,StringBuilder则不是。

2.String、StringBuffer和StringBuilder的总结

1).  String和StringBuffer、StringBuilder相比,String是不可变的,String的每次修改操作都是在内存中重新new一个对象出来,而StringBuffer、StringBuilder则不用,并且提供了一定的缓存功能,默认16个字节数组的大小,超过默认的数组长度时,则扩容为原来字节数组的长度*2+2。2).  StringBuffer和StringBuilder相比,StringBuffer是synchronized的,是线程安全的,而StringBuilder是非线程安全的,单线程情况下性能更好一点;使用StringBuffer和StringBuilder时,可以适当考虑下初始化大小,较少扩容的次数,提高代码的高效性。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表