Home | History | Annotate | Download | only in lang
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.lang;
     19 
     20 import java.io.IOException;
     21 import java.io.ObjectInputStream;
     22 import java.io.ObjectOutputStream;
     23 import java.io.ObjectStreamField;
     24 import java.io.Serializable;
     25 
     26 /**
     27  * A modifiable {@link CharSequence sequence of characters} for use in creating
     28  * strings, where all accesses are synchronized. This class has mostly been replaced
     29  * by {@link StringBuilder} because this synchronization is rarely useful. This
     30  * class is mainly used to interact with legacy APIs that expose it.
     31  *
     32  * <p>For particularly complex string-building needs, consider {@link java.util.Formatter}.
     33  *
     34  * <p>The majority of the modification methods on this class return {@code
     35  * this} so that method calls can be chained together. For example:
     36  * {@code new StringBuffer("a").append("b").append("c").toString()}.
     37  *
     38  * @see CharSequence
     39  * @see Appendable
     40  * @see StringBuilder
     41  * @see String
     42  * @see String.format
     43  * @since 1.0
     44  */
     45 public final class StringBuffer extends AbstractStringBuilder implements
     46         Appendable, Serializable, CharSequence {
     47 
     48     private static final long serialVersionUID = 3388685877147921107L;
     49 
     50     private static final ObjectStreamField serialPersistentFields[] = {
     51             new ObjectStreamField("count", int.class), //$NON-NLS-1$
     52             new ObjectStreamField("shared", boolean.class), //$NON-NLS-1$
     53             new ObjectStreamField("value", char[].class), }; //$NON-NLS-1$
     54 
     55     /**
     56      * Constructs a new StringBuffer using the default capacity which is 16.
     57      */
     58     public StringBuffer() {
     59         super();
     60     }
     61 
     62     /**
     63      * Constructs a new StringBuffer using the specified capacity.
     64      *
     65      * @param capacity
     66      *            the initial capacity.
     67      */
     68     public StringBuffer(int capacity) {
     69         super(capacity);
     70     }
     71 
     72     /**
     73      * Constructs a new StringBuffer containing the characters in the specified
     74      * string. The capacity of the new buffer will be the length of the
     75      * {@code String} plus the default capacity.
     76      *
     77      * @param string
     78      *            the string content with which to initialize the new instance.
     79      * @throws NullPointerException
     80      *            if {@code string} is {@code null}.
     81      */
     82     public StringBuffer(String string) {
     83         super(string);
     84     }
     85 
     86     /**
     87      * Constructs a StringBuffer and initializes it with the content from the
     88      * specified {@code CharSequence}. The capacity of the new buffer will be
     89      * the length of the {@code CharSequence} plus the default capacity.
     90      *
     91      * @param cs
     92      *            the content to initialize the instance.
     93      * @throws NullPointerException
     94      *            if {@code cs} is {@code null}.
     95      * @since 1.5
     96      */
     97     public StringBuffer(CharSequence cs) {
     98         super(cs.toString());
     99     }
    100 
    101     /**
    102      * Adds the string representation of the specified boolean to the end of
    103      * this StringBuffer.
    104      * <p>
    105      * If the argument is {@code true} the string {@code "true"} is appended,
    106      * otherwise the string {@code "false"} is appended.
    107      *
    108      * @param b
    109      *            the boolean to append.
    110      * @return this StringBuffer.
    111      * @see String#valueOf(boolean)
    112      */
    113     public StringBuffer append(boolean b) {
    114         return append(b ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
    115     }
    116 
    117     /**
    118      * Adds the specified character to the end of this buffer.
    119      *
    120      * @param ch
    121      *            the character to append.
    122      * @return this StringBuffer.
    123      * @see String#valueOf(char)
    124      */
    125     public synchronized StringBuffer append(char ch) {
    126         append0(ch);
    127         return this;
    128     }
    129 
    130     /**
    131      * Adds the string representation of the specified double to the end of this
    132      * StringBuffer.
    133      *
    134      * @param d
    135      *            the double to append.
    136      * @return this StringBuffer.
    137      * @see String#valueOf(double)
    138      */
    139     public StringBuffer append(double d) {
    140         return append(Double.toString(d));
    141     }
    142 
    143     /**
    144      * Adds the string representation of the specified float to the end of this
    145      * StringBuffer.
    146      *
    147      * @param f
    148      *            the float to append.
    149      * @return this StringBuffer.
    150      * @see String#valueOf(float)
    151      */
    152     public StringBuffer append(float f) {
    153         return append(Float.toString(f));
    154     }
    155 
    156     /**
    157      * Adds the string representation of the specified integer to the end of
    158      * this StringBuffer.
    159      *
    160      * @param i
    161      *            the integer to append.
    162      * @return this StringBuffer.
    163      * @see String#valueOf(int)
    164      */
    165     public StringBuffer append(int i) {
    166         return append(Integer.toString(i));
    167     }
    168 
    169     /**
    170      * Adds the string representation of the specified long to the end of this
    171      * StringBuffer.
    172      *
    173      * @param l
    174      *            the long to append.
    175      * @return this StringBuffer.
    176      * @see String#valueOf(long)
    177      */
    178     public StringBuffer append(long l) {
    179         return append(Long.toString(l));
    180     }
    181 
    182     /**
    183      * Adds the string representation of the specified object to the end of this
    184      * StringBuffer.
    185      * <p>
    186      * If the specified object is {@code null} the string {@code "null"} is
    187      * appended, otherwise the objects {@code toString} is used to get its
    188      * string representation.
    189      *
    190      * @param obj
    191      *            the object to append (may be null).
    192      * @return this StringBuffer.
    193      * @see String#valueOf(Object)
    194      */
    195     public synchronized StringBuffer append(Object obj) {
    196         if (obj == null) {
    197             appendNull();
    198         } else {
    199             append0(obj.toString());
    200         }
    201         return this;
    202     }
    203 
    204     /**
    205      * Adds the specified string to the end of this buffer.
    206      * <p>
    207      * If the specified string is {@code null} the string {@code "null"} is
    208      * appended, otherwise the contents of the specified string is appended.
    209      *
    210      * @param string
    211      *            the string to append (may be null).
    212      * @return this StringBuffer.
    213      */
    214     public synchronized StringBuffer append(String string) {
    215         append0(string);
    216         return this;
    217     }
    218 
    219     /**
    220      * Adds the specified StringBuffer to the end of this buffer.
    221      * <p>
    222      * If the specified StringBuffer is {@code null} the string {@code "null"}
    223      * is appended, otherwise the contents of the specified StringBuffer is
    224      * appended.
    225      *
    226      * @param sb
    227      *            the StringBuffer to append (may be null).
    228      * @return this StringBuffer.
    229      *
    230      * @since 1.4
    231      */
    232     public synchronized StringBuffer append(StringBuffer sb) {
    233         if (sb == null) {
    234             appendNull();
    235         } else {
    236             synchronized (sb) {
    237                 append0(sb.getValue(), 0, sb.length());
    238             }
    239         }
    240         return this;
    241     }
    242 
    243     /**
    244      * Adds the character array to the end of this buffer.
    245      *
    246      * @param chars
    247      *            the character array to append.
    248      * @return this StringBuffer.
    249      * @throws NullPointerException
    250      *            if {@code chars} is {@code null}.
    251      */
    252     public synchronized StringBuffer append(char chars[]) {
    253         append0(chars);
    254         return this;
    255     }
    256 
    257     /**
    258      * Adds the specified sequence of characters to the end of this buffer.
    259      *
    260      * @param chars
    261      *            the character array to append.
    262      * @param start
    263      *            the starting offset.
    264      * @param length
    265      *            the number of characters.
    266      * @return this StringBuffer.
    267      * @throws ArrayIndexOutOfBoundsException
    268      *             if {@code length < 0} , {@code start < 0} or {@code start +
    269      *             length > chars.length}.
    270      * @throws NullPointerException
    271      *            if {@code chars} is {@code null}.
    272      */
    273     public synchronized StringBuffer append(char chars[], int start, int length) {
    274         append0(chars, start, length);
    275         return this;
    276     }
    277 
    278     /**
    279      * Appends the specified CharSequence to this buffer.
    280      * <p>
    281      * If the specified CharSequence is {@code null} the string {@code "null"}
    282      * is appended, otherwise the contents of the specified CharSequence is
    283      * appended.
    284      *
    285      * @param s
    286      *            the CharSequence to append.
    287      * @return this StringBuffer.
    288      * @since 1.5
    289      */
    290     public synchronized StringBuffer append(CharSequence s) {
    291         if (s == null) {
    292             appendNull();
    293         } else {
    294             append0(s.toString());
    295         }
    296         return this;
    297     }
    298 
    299     /**
    300      * Appends the specified subsequence of the CharSequence to this buffer.
    301      * <p>
    302      * If the specified CharSequence is {@code null}, then the string {@code
    303      * "null"} is used to extract a subsequence.
    304      *
    305      * @param s
    306      *            the CharSequence to append.
    307      * @param start
    308      *            the inclusive start index.
    309      * @param end
    310      *            the exclusive end index.
    311      * @return this StringBuffer.
    312      * @throws IndexOutOfBoundsException
    313      *             if {@code start} or {@code end} are negative, {@code start}
    314      *             is greater than {@code end} or {@code end} is greater than
    315      *             the length of {@code s}.
    316      * @since 1.5
    317      */
    318     public synchronized StringBuffer append(CharSequence s, int start, int end) {
    319         append0(s, start, end);
    320         return this;
    321     }
    322 
    323     /**
    324      * Appends the string representation of the specified Unicode code point to
    325      * the end of this buffer.
    326      * <p>
    327      * The code point is converted to a {@code char[]} as defined by
    328      * {@link Character#toChars(int)}.
    329      *
    330      * @param codePoint
    331      *            the Unicode code point to encode and append.
    332      * @return this StringBuffer.
    333      * @see Character#toChars(int)
    334      * @since 1.5
    335      */
    336     public StringBuffer appendCodePoint(int codePoint) {
    337         return append(Character.toChars(codePoint));
    338     }
    339 
    340     @Override
    341     public synchronized char charAt(int index) {
    342         return super.charAt(index);
    343     }
    344 
    345     @Override
    346     public synchronized int codePointAt(int index) {
    347         return super.codePointAt(index);
    348     }
    349 
    350     @Override
    351     public synchronized int codePointBefore(int index) {
    352         return super.codePointBefore(index);
    353     }
    354 
    355     @Override
    356     public synchronized int codePointCount(int beginIndex, int endIndex) {
    357         return super.codePointCount(beginIndex, endIndex);
    358     }
    359 
    360     /**
    361      * Deletes a range of characters.
    362      *
    363      * @param start
    364      *            the offset of the first character.
    365      * @param end
    366      *            the offset one past the last character.
    367      * @return this StringBuffer.
    368      * @throws StringIndexOutOfBoundsException
    369      *             if {@code start < 0}, {@code start > end} or {@code end >
    370      *             length()}.
    371      */
    372     public synchronized StringBuffer delete(int start, int end) {
    373         delete0(start, end);
    374         return this;
    375     }
    376 
    377     /**
    378      * Deletes the character at the specified offset.
    379      *
    380      * @param location
    381      *            the offset of the character to delete.
    382      * @return this StringBuffer.
    383      * @throws StringIndexOutOfBoundsException
    384      *             if {@code location < 0} or {@code location >= length()}
    385      */
    386     public synchronized StringBuffer deleteCharAt(int location) {
    387         deleteCharAt0(location);
    388         return this;
    389     }
    390 
    391     @Override
    392     public synchronized void ensureCapacity(int min) {
    393         super.ensureCapacity(min);
    394     }
    395 
    396     /**
    397      * Copies the requested sequence of characters to the {@code char[]} passed
    398      * starting at {@code idx}.
    399      *
    400      * @param start
    401      *            the starting offset of characters to copy.
    402      * @param end
    403      *            the ending offset of characters to copy.
    404      * @param buffer
    405      *            the destination character array.
    406      * @param idx
    407      *            the starting offset in the character array.
    408      * @throws IndexOutOfBoundsException
    409      *             if {@code start < 0}, {@code end > length()}, {@code start >
    410      *             end}, {@code index < 0}, {@code end - start > buffer.length -
    411      *             index}
    412      */
    413     @Override
    414     public synchronized void getChars(int start, int end, char[] buffer, int idx) {
    415         super.getChars(start, end, buffer, idx);
    416     }
    417 
    418     @Override
    419     public synchronized int indexOf(String subString, int start) {
    420         return super.indexOf(subString, start);
    421     }
    422 
    423     /**
    424      * Inserts the character into this buffer at the specified offset.
    425      *
    426      * @param index
    427      *            the index at which to insert.
    428      * @param ch
    429      *            the character to insert.
    430      * @return this buffer.
    431      * @throws ArrayIndexOutOfBoundsException
    432      *             if {@code index < 0} or {@code index > length()}.
    433      */
    434     public synchronized StringBuffer insert(int index, char ch) {
    435         insert0(index, ch);
    436         return this;
    437     }
    438 
    439     /**
    440      * Inserts the string representation of the specified boolean into this
    441      * buffer at the specified offset.
    442      *
    443      * @param index
    444      *            the index at which to insert.
    445      * @param b
    446      *            the boolean to insert.
    447      * @return this buffer.
    448      * @throws StringIndexOutOfBoundsException
    449      *             if {@code index < 0} or {@code index > length()}.
    450      */
    451     public StringBuffer insert(int index, boolean b) {
    452         return insert(index, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
    453     }
    454 
    455     /**
    456      * Inserts the string representation of the specified integer into this
    457      * buffer at the specified offset.
    458      *
    459      * @param index
    460      *            the index at which to insert.
    461      * @param i
    462      *            the integer to insert.
    463      * @return this buffer.
    464      * @throws StringIndexOutOfBoundsException
    465      *             if {@code index < 0} or {@code index > length()}.
    466      */
    467     public StringBuffer insert(int index, int i) {
    468         return insert(index, Integer.toString(i));
    469     }
    470 
    471     /**
    472      * Inserts the string representation of the specified long into this buffer
    473      * at the specified offset.
    474      *
    475      * @param index
    476      *            the index at which to insert.
    477      * @param l
    478      *            the long to insert.
    479      * @return this buffer.
    480      * @throws StringIndexOutOfBoundsException
    481      *             if {@code index < 0} or {@code index > length()}.
    482      */
    483     public StringBuffer insert(int index, long l) {
    484         return insert(index, Long.toString(l));
    485     }
    486 
    487     /**
    488      * Inserts the string representation of the specified into this buffer
    489      * double at the specified offset.
    490      *
    491      * @param index
    492      *            the index at which to insert.
    493      * @param d
    494      *            the double to insert.
    495      * @return this buffer.
    496      * @throws StringIndexOutOfBoundsException
    497      *             if {@code index < 0} or {@code index > length()}.
    498      */
    499     public StringBuffer insert(int index, double d) {
    500         return insert(index, Double.toString(d));
    501     }
    502 
    503     /**
    504      * Inserts the string representation of the specified float into this buffer
    505      * at the specified offset.
    506      *
    507      * @param index
    508      *            the index at which to insert.
    509      * @param f
    510      *            the float to insert.
    511      * @return this buffer.
    512      * @throws StringIndexOutOfBoundsException
    513      *             if {@code index < 0} or {@code index > length()}.
    514      */
    515     public StringBuffer insert(int index, float f) {
    516         return insert(index, Float.toString(f));
    517     }
    518 
    519     /**
    520      * Inserts the string representation of the specified object into this
    521      * buffer at the specified offset.
    522      * <p>
    523      * If the specified object is {@code null}, the string {@code "null"} is
    524      * inserted, otherwise the objects {@code toString} method is used to get
    525      * its string representation.
    526      *
    527      * @param index
    528      *            the index at which to insert.
    529      * @param obj
    530      *            the object to insert (may be null).
    531      * @return this buffer.
    532      * @throws StringIndexOutOfBoundsException
    533      *             if {@code index < 0} or {@code index > length()}.
    534      */
    535     public StringBuffer insert(int index, Object obj) {
    536         return insert(index, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
    537     }
    538 
    539     /**
    540      * Inserts the string into this buffer at the specified offset.
    541      * <p>
    542      * If the specified string is {@code null}, the string {@code "null"} is
    543      * inserted, otherwise the contents of the string is inserted.
    544      *
    545      * @param index
    546      *            the index at which to insert.
    547      * @param string
    548      *            the string to insert (may be null).
    549      * @return this buffer.
    550      * @throws StringIndexOutOfBoundsException
    551      *             if {@code index < 0} or {@code index > length()}.
    552      */
    553     public synchronized StringBuffer insert(int index, String string) {
    554         insert0(index, string);
    555         return this;
    556     }
    557 
    558     /**
    559      * Inserts the character array into this buffer at the specified offset.
    560      *
    561      * @param index
    562      *            the index at which to insert.
    563      * @param chars
    564      *            the character array to insert.
    565      * @return this buffer.
    566      * @throws StringIndexOutOfBoundsException
    567      *             if {@code index < 0} or {@code index > length()}.
    568      * @throws NullPointerException
    569      *            if {@code chars} is {@code null}.
    570      */
    571     public synchronized StringBuffer insert(int index, char[] chars) {
    572         insert0(index, chars);
    573         return this;
    574     }
    575 
    576     /**
    577      * Inserts the specified subsequence of characters into this buffer at the
    578      * specified index.
    579      *
    580      * @param index
    581      *            the index at which to insert.
    582      * @param chars
    583      *            the character array to insert.
    584      * @param start
    585      *            the starting offset.
    586      * @param length
    587      *            the number of characters.
    588      * @return this buffer.
    589      * @throws NullPointerException
    590      *             if {@code chars} is {@code null}.
    591      * @throws StringIndexOutOfBoundsException
    592      *             if {@code length < 0}, {@code start < 0}, {@code start +
    593      *             length > chars.length}, {@code index < 0} or {@code index >
    594      *             length()}
    595      */
    596     public synchronized StringBuffer insert(int index, char chars[], int start,
    597             int length) {
    598         insert0(index, chars, start, length);
    599         return this;
    600     }
    601 
    602     /**
    603      * Inserts the specified CharSequence into this buffer at the specified
    604      * index.
    605      * <p>
    606      * If the specified CharSequence is {@code null}, the string {@code "null"}
    607      * is inserted, otherwise the contents of the CharSequence.
    608      *
    609      * @param index
    610      *            The index at which to insert.
    611      * @param s
    612      *            The char sequence to insert.
    613      * @return this buffer.
    614      * @throws IndexOutOfBoundsException
    615      *             if {@code index < 0} or {@code index > length()}.
    616      * @since 1.5
    617      */
    618     public synchronized StringBuffer insert(int index, CharSequence s) {
    619         insert0(index, s == null ? "null" : s.toString()); //$NON-NLS-1$
    620         return this;
    621     }
    622 
    623     /**
    624      * Inserts the specified subsequence into this buffer at the specified
    625      * index.
    626      * <p>
    627      * If the specified CharSequence is {@code null}, the string {@code "null"}
    628      * is inserted, otherwise the contents of the CharSequence.
    629      *
    630      * @param index
    631      *            The index at which to insert.
    632      * @param s
    633      *            The char sequence to insert.
    634      * @param start
    635      *            The inclusive start index in the char sequence.
    636      * @param end
    637      *            The exclusive end index in the char sequence.
    638      * @return this buffer.
    639      * @throws IndexOutOfBoundsException
    640      *             if {@code index} is negative or greater than the current
    641      *             length, {@code start} or {@code end} are negative, {@code
    642      *             start} is greater than {@code end} or {@code end} is greater
    643      *             than the length of {@code s}.
    644      * @since 1.5
    645      */
    646     public synchronized StringBuffer insert(int index, CharSequence s,
    647             int start, int end) {
    648         insert0(index, s, start, end);
    649         return this;
    650     }
    651 
    652     @Override
    653     public synchronized int lastIndexOf(String subString, int start) {
    654         return super.lastIndexOf(subString, start);
    655     }
    656 
    657     @Override
    658     public synchronized int offsetByCodePoints(int index, int codePointOffset) {
    659         return super.offsetByCodePoints(index, codePointOffset);
    660     }
    661 
    662     /**
    663      * Replaces the characters in the specified range with the contents of the
    664      * specified string.
    665      *
    666      * @param start
    667      *            the inclusive begin index.
    668      * @param end
    669      *            the exclusive end index.
    670      * @param string
    671      *            the string that will replace the contents in the range.
    672      * @return this buffer.
    673      * @throws StringIndexOutOfBoundsException
    674      *             if {@code start} or {@code end} are negative, {@code start}
    675      *             is greater than {@code end} or {@code end} is greater than
    676      *             the length of {@code s}.
    677      */
    678     public synchronized StringBuffer replace(int start, int end, String string) {
    679         replace0(start, end, string);
    680         return this;
    681     }
    682 
    683     /**
    684      * Reverses the order of characters in this buffer.
    685      *
    686      * @return this buffer.
    687      */
    688     public synchronized StringBuffer reverse() {
    689         reverse0();
    690         return this;
    691     }
    692 
    693     @Override
    694     public synchronized void setCharAt(int index, char ch) {
    695         super.setCharAt(index, ch);
    696     }
    697 
    698     @Override
    699     public synchronized void setLength(int length) {
    700         super.setLength(length);
    701     }
    702 
    703     @Override
    704     public synchronized CharSequence subSequence(int start, int end) {
    705         return super.substring(start, end);
    706     }
    707 
    708     @Override
    709     public synchronized String substring(int start) {
    710         return super.substring(start);
    711     }
    712 
    713     @Override
    714     public synchronized String substring(int start, int end) {
    715         return super.substring(start, end);
    716     }
    717 
    718     @Override
    719     public synchronized String toString() {
    720         return super.toString();
    721     }
    722 
    723     @Override
    724     public synchronized void trimToSize() {
    725         super.trimToSize();
    726     }
    727 
    728     private synchronized void writeObject(ObjectOutputStream out)
    729             throws IOException {
    730         ObjectOutputStream.PutField fields = out.putFields();
    731         fields.put("count", length()); //$NON-NLS-1$
    732         fields.put("shared", false); //$NON-NLS-1$
    733         fields.put("value", getValue()); //$NON-NLS-1$
    734         out.writeFields();
    735     }
    736 
    737     private void readObject(ObjectInputStream in) throws IOException,
    738             ClassNotFoundException {
    739         ObjectInputStream.GetField fields = in.readFields();
    740         int count = fields.get("count", 0); //$NON-NLS-1$
    741         char[] value = (char[]) fields.get("value", null); //$NON-NLS-1$
    742         set(value, count);
    743     }
    744 }
    745