• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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),
52         new ObjectStreamField("shared", boolean.class),
53         new ObjectStreamField("value", char[].class),
54     };
55 
56     /**
57      * Constructs a new StringBuffer using the default capacity which is 16.
58      */
StringBuffer()59     public StringBuffer() {
60     }
61 
62     /**
63      * Constructs a new StringBuffer using the specified capacity.
64      *
65      * @param capacity
66      *            the initial capacity.
67      */
StringBuffer(int capacity)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      */
StringBuffer(String string)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      */
StringBuffer(CharSequence cs)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      */
append(boolean b)113     public StringBuffer append(boolean b) {
114         return append(b ? "true" : "false");
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      */
append(char ch)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      */
append(double d)139     public StringBuffer append(double d) {
140         RealToString.getInstance().appendDouble(this, d);
141         return this;
142     }
143 
144     /**
145      * Adds the string representation of the specified float to the end of this
146      * StringBuffer.
147      *
148      * @param f
149      *            the float to append.
150      * @return this StringBuffer.
151      * @see String#valueOf(float)
152      */
append(float f)153     public StringBuffer append(float f) {
154         RealToString.getInstance().appendFloat(this, f);
155         return this;
156     }
157 
158     /**
159      * Adds the string representation of the specified integer to the end of
160      * this StringBuffer.
161      *
162      * @param i
163      *            the integer to append.
164      * @return this StringBuffer.
165      * @see String#valueOf(int)
166      */
append(int i)167     public StringBuffer append(int i) {
168         IntegralToString.appendInt(this, i);
169         return this;
170     }
171 
172     /**
173      * Adds the string representation of the specified long to the end of this
174      * StringBuffer.
175      *
176      * @param l
177      *            the long to append.
178      * @return this StringBuffer.
179      * @see String#valueOf(long)
180      */
append(long l)181     public StringBuffer append(long l) {
182         IntegralToString.appendLong(this, l);
183         return this;
184     }
185 
186     /**
187      * Adds the string representation of the specified object to the end of this
188      * StringBuffer.
189      * <p>
190      * If the specified object is {@code null} the string {@code "null"} is
191      * appended, otherwise the objects {@code toString} is used to get its
192      * string representation.
193      *
194      * @param obj
195      *            the object to append (may be null).
196      * @return this StringBuffer.
197      * @see String#valueOf(Object)
198      */
append(Object obj)199     public synchronized StringBuffer append(Object obj) {
200         if (obj == null) {
201             appendNull();
202         } else {
203             append0(obj.toString());
204         }
205         return this;
206     }
207 
208     /**
209      * Adds the specified string to the end of this buffer.
210      * <p>
211      * If the specified string is {@code null} the string {@code "null"} is
212      * appended, otherwise the contents of the specified string is appended.
213      *
214      * @param string
215      *            the string to append (may be null).
216      * @return this StringBuffer.
217      */
append(String string)218     public synchronized StringBuffer append(String string) {
219         append0(string);
220         return this;
221     }
222 
223     /**
224      * Adds the specified StringBuffer to the end of this buffer.
225      * <p>
226      * If the specified StringBuffer is {@code null} the string {@code "null"}
227      * is appended, otherwise the contents of the specified StringBuffer is
228      * appended.
229      *
230      * @param sb
231      *            the StringBuffer to append (may be null).
232      * @return this StringBuffer.
233      *
234      * @since 1.4
235      */
append(StringBuffer sb)236     public synchronized StringBuffer append(StringBuffer sb) {
237         if (sb == null) {
238             appendNull();
239         } else {
240             synchronized (sb) {
241                 append0(sb.getValue(), 0, sb.length());
242             }
243         }
244         return this;
245     }
246 
247     /**
248      * Adds the character array to the end of this buffer.
249      *
250      * @param chars
251      *            the character array to append.
252      * @return this StringBuffer.
253      * @throws NullPointerException
254      *            if {@code chars} is {@code null}.
255      */
append(char[] chars)256     public synchronized StringBuffer append(char[] chars) {
257         append0(chars);
258         return this;
259     }
260 
261     /**
262      * Adds the specified sequence of characters to the end of this buffer.
263      *
264      * @param chars
265      *            the character array to append.
266      * @param start
267      *            the starting offset.
268      * @param length
269      *            the number of characters.
270      * @return this StringBuffer.
271      * @throws ArrayIndexOutOfBoundsException
272      *             if {@code length < 0} , {@code start < 0} or {@code start +
273      *             length > chars.length}.
274      * @throws NullPointerException
275      *            if {@code chars} is {@code null}.
276      */
append(char[] chars, int start, int length)277     public synchronized StringBuffer append(char[] chars, int start, int length) {
278         append0(chars, start, length);
279         return this;
280     }
281 
282     /**
283      * Appends the specified CharSequence to this buffer.
284      * <p>
285      * If the specified CharSequence is {@code null} the string {@code "null"}
286      * is appended, otherwise the contents of the specified CharSequence is
287      * appended.
288      *
289      * @param s
290      *            the CharSequence to append.
291      * @return this StringBuffer.
292      * @since 1.5
293      */
append(CharSequence s)294     public synchronized StringBuffer append(CharSequence s) {
295         if (s == null) {
296             appendNull();
297         } else {
298             append0(s, 0, s.length());
299         }
300         return this;
301     }
302 
303     /**
304      * Appends the specified subsequence of the CharSequence to this buffer.
305      * <p>
306      * If the specified CharSequence is {@code null}, then the string {@code
307      * "null"} is used to extract a subsequence.
308      *
309      * @param s
310      *            the CharSequence to append.
311      * @param start
312      *            the inclusive start index.
313      * @param end
314      *            the exclusive end index.
315      * @return this StringBuffer.
316      * @throws IndexOutOfBoundsException
317      *             if {@code start} or {@code end} are negative, {@code start}
318      *             is greater than {@code end} or {@code end} is greater than
319      *             the length of {@code s}.
320      * @since 1.5
321      */
append(CharSequence s, int start, int end)322     public synchronized StringBuffer append(CharSequence s, int start, int end) {
323         append0(s, start, end);
324         return this;
325     }
326 
327     /**
328      * Appends the string representation of the specified Unicode code point to
329      * the end of this buffer.
330      * <p>
331      * The code point is converted to a {@code char[]} as defined by
332      * {@link Character#toChars(int)}.
333      *
334      * @param codePoint
335      *            the Unicode code point to encode and append.
336      * @return this StringBuffer.
337      * @see Character#toChars(int)
338      * @since 1.5
339      */
appendCodePoint(int codePoint)340     public StringBuffer appendCodePoint(int codePoint) {
341         return append(Character.toChars(codePoint));
342     }
343 
344     @Override
charAt(int index)345     public synchronized char charAt(int index) {
346         return super.charAt(index);
347     }
348 
349     @Override
codePointAt(int index)350     public synchronized int codePointAt(int index) {
351         return super.codePointAt(index);
352     }
353 
354     @Override
codePointBefore(int index)355     public synchronized int codePointBefore(int index) {
356         return super.codePointBefore(index);
357     }
358 
359     @Override
codePointCount(int beginIndex, int endIndex)360     public synchronized int codePointCount(int beginIndex, int endIndex) {
361         return super.codePointCount(beginIndex, endIndex);
362     }
363 
364     /**
365      * Deletes a range of characters.
366      *
367      * @param start
368      *            the offset of the first character.
369      * @param end
370      *            the offset one past the last character.
371      * @return this StringBuffer.
372      * @throws StringIndexOutOfBoundsException
373      *             if {@code start < 0}, {@code start > end} or {@code end >
374      *             length()}.
375      */
delete(int start, int end)376     public synchronized StringBuffer delete(int start, int end) {
377         delete0(start, end);
378         return this;
379     }
380 
381     /**
382      * Deletes the character at the specified offset.
383      *
384      * @param location
385      *            the offset of the character to delete.
386      * @return this StringBuffer.
387      * @throws StringIndexOutOfBoundsException
388      *             if {@code location < 0} or {@code location >= length()}
389      */
deleteCharAt(int location)390     public synchronized StringBuffer deleteCharAt(int location) {
391         deleteCharAt0(location);
392         return this;
393     }
394 
395     @Override
ensureCapacity(int min)396     public synchronized void ensureCapacity(int min) {
397         super.ensureCapacity(min);
398     }
399 
400     /**
401      * Copies the requested sequence of characters to the {@code char[]} passed
402      * starting at {@code idx}.
403      *
404      * @param start
405      *            the starting offset of characters to copy.
406      * @param end
407      *            the ending offset of characters to copy.
408      * @param buffer
409      *            the destination character array.
410      * @param idx
411      *            the starting offset in the character array.
412      * @throws IndexOutOfBoundsException
413      *             if {@code start < 0}, {@code end > length()}, {@code start >
414      *             end}, {@code index < 0}, {@code end - start > buffer.length -
415      *             index}
416      */
417     @Override
getChars(int start, int end, char[] buffer, int idx)418     public synchronized void getChars(int start, int end, char[] buffer, int idx) {
419         super.getChars(start, end, buffer, idx);
420     }
421 
422     @Override
indexOf(String subString, int start)423     public synchronized int indexOf(String subString, int start) {
424         return super.indexOf(subString, start);
425     }
426 
427     /**
428      * Inserts the character into this buffer at the specified offset.
429      *
430      * @param index
431      *            the index at which to insert.
432      * @param ch
433      *            the character to insert.
434      * @return this buffer.
435      * @throws ArrayIndexOutOfBoundsException
436      *             if {@code index < 0} or {@code index > length()}.
437      */
insert(int index, char ch)438     public synchronized StringBuffer insert(int index, char ch) {
439         insert0(index, ch);
440         return this;
441     }
442 
443     /**
444      * Inserts the string representation of the specified boolean into this
445      * buffer at the specified offset.
446      *
447      * @param index
448      *            the index at which to insert.
449      * @param b
450      *            the boolean to insert.
451      * @return this buffer.
452      * @throws StringIndexOutOfBoundsException
453      *             if {@code index < 0} or {@code index > length()}.
454      */
insert(int index, boolean b)455     public StringBuffer insert(int index, boolean b) {
456         return insert(index, b ? "true" : "false");
457     }
458 
459     /**
460      * Inserts the string representation of the specified integer into this
461      * buffer at the specified offset.
462      *
463      * @param index
464      *            the index at which to insert.
465      * @param i
466      *            the integer to insert.
467      * @return this buffer.
468      * @throws StringIndexOutOfBoundsException
469      *             if {@code index < 0} or {@code index > length()}.
470      */
insert(int index, int i)471     public StringBuffer insert(int index, int i) {
472         return insert(index, Integer.toString(i));
473     }
474 
475     /**
476      * Inserts the string representation of the specified long into this buffer
477      * at the specified offset.
478      *
479      * @param index
480      *            the index at which to insert.
481      * @param l
482      *            the long to insert.
483      * @return this buffer.
484      * @throws StringIndexOutOfBoundsException
485      *             if {@code index < 0} or {@code index > length()}.
486      */
insert(int index, long l)487     public StringBuffer insert(int index, long l) {
488         return insert(index, Long.toString(l));
489     }
490 
491     /**
492      * Inserts the string representation of the specified into this buffer
493      * double at the specified offset.
494      *
495      * @param index
496      *            the index at which to insert.
497      * @param d
498      *            the double to insert.
499      * @return this buffer.
500      * @throws StringIndexOutOfBoundsException
501      *             if {@code index < 0} or {@code index > length()}.
502      */
insert(int index, double d)503     public StringBuffer insert(int index, double d) {
504         return insert(index, Double.toString(d));
505     }
506 
507     /**
508      * Inserts the string representation of the specified float into this buffer
509      * at the specified offset.
510      *
511      * @param index
512      *            the index at which to insert.
513      * @param f
514      *            the float to insert.
515      * @return this buffer.
516      * @throws StringIndexOutOfBoundsException
517      *             if {@code index < 0} or {@code index > length()}.
518      */
insert(int index, float f)519     public StringBuffer insert(int index, float f) {
520         return insert(index, Float.toString(f));
521     }
522 
523     /**
524      * Inserts the string representation of the specified object into this
525      * buffer at the specified offset.
526      * <p>
527      * If the specified object is {@code null}, the string {@code "null"} is
528      * inserted, otherwise the objects {@code toString} method is used to get
529      * its string representation.
530      *
531      * @param index
532      *            the index at which to insert.
533      * @param obj
534      *            the object to insert (may be null).
535      * @return this buffer.
536      * @throws StringIndexOutOfBoundsException
537      *             if {@code index < 0} or {@code index > length()}.
538      */
insert(int index, Object obj)539     public StringBuffer insert(int index, Object obj) {
540         return insert(index, obj == null ? "null" : obj.toString());
541     }
542 
543     /**
544      * Inserts the string into this buffer at the specified offset.
545      * <p>
546      * If the specified string is {@code null}, the string {@code "null"} is
547      * inserted, otherwise the contents of the string is inserted.
548      *
549      * @param index
550      *            the index at which to insert.
551      * @param string
552      *            the string to insert (may be null).
553      * @return this buffer.
554      * @throws StringIndexOutOfBoundsException
555      *             if {@code index < 0} or {@code index > length()}.
556      */
insert(int index, String string)557     public synchronized StringBuffer insert(int index, String string) {
558         insert0(index, string);
559         return this;
560     }
561 
562     /**
563      * Inserts the character array into this buffer at the specified offset.
564      *
565      * @param index
566      *            the index at which to insert.
567      * @param chars
568      *            the character array to insert.
569      * @return this buffer.
570      * @throws StringIndexOutOfBoundsException
571      *             if {@code index < 0} or {@code index > length()}.
572      * @throws NullPointerException
573      *            if {@code chars} is {@code null}.
574      */
insert(int index, char[] chars)575     public synchronized StringBuffer insert(int index, char[] chars) {
576         insert0(index, chars);
577         return this;
578     }
579 
580     /**
581      * Inserts the specified subsequence of characters into this buffer at the
582      * specified index.
583      *
584      * @param index
585      *            the index at which to insert.
586      * @param chars
587      *            the character array to insert.
588      * @param start
589      *            the starting offset.
590      * @param length
591      *            the number of characters.
592      * @return this buffer.
593      * @throws NullPointerException
594      *             if {@code chars} is {@code null}.
595      * @throws StringIndexOutOfBoundsException
596      *             if {@code length < 0}, {@code start < 0}, {@code start +
597      *             length > chars.length}, {@code index < 0} or {@code index >
598      *             length()}
599      */
insert(int index, char[] chars, int start, int length)600     public synchronized StringBuffer insert(int index, char[] chars, int start, int length) {
601         insert0(index, chars, start, length);
602         return this;
603     }
604 
605     /**
606      * Inserts the specified CharSequence into this buffer at the specified
607      * index.
608      * <p>
609      * If the specified CharSequence is {@code null}, the string {@code "null"}
610      * is inserted, otherwise the contents of the CharSequence.
611      *
612      * @param index
613      *            The index at which to insert.
614      * @param s
615      *            The char sequence to insert.
616      * @return this buffer.
617      * @throws IndexOutOfBoundsException
618      *             if {@code index < 0} or {@code index > length()}.
619      * @since 1.5
620      */
insert(int index, CharSequence s)621     public synchronized StringBuffer insert(int index, CharSequence s) {
622         insert0(index, s == null ? "null" : s.toString());
623         return this;
624     }
625 
626     /**
627      * Inserts the specified subsequence into this buffer at the specified
628      * index.
629      * <p>
630      * If the specified CharSequence is {@code null}, the string {@code "null"}
631      * is inserted, otherwise the contents of the CharSequence.
632      *
633      * @param index
634      *            The index at which to insert.
635      * @param s
636      *            The char sequence to insert.
637      * @param start
638      *            The inclusive start index in the char sequence.
639      * @param end
640      *            The exclusive end index in the char sequence.
641      * @return this buffer.
642      * @throws IndexOutOfBoundsException
643      *             if {@code index} is negative or greater than the current
644      *             length, {@code start} or {@code end} are negative, {@code
645      *             start} is greater than {@code end} or {@code end} is greater
646      *             than the length of {@code s}.
647      * @since 1.5
648      */
insert(int index, CharSequence s, int start, int end)649     public synchronized StringBuffer insert(int index, CharSequence s,
650             int start, int end) {
651         insert0(index, s, start, end);
652         return this;
653     }
654 
655     @Override
lastIndexOf(String subString, int start)656     public synchronized int lastIndexOf(String subString, int start) {
657         return super.lastIndexOf(subString, start);
658     }
659 
660     @Override
offsetByCodePoints(int index, int codePointOffset)661     public synchronized int offsetByCodePoints(int index, int codePointOffset) {
662         return super.offsetByCodePoints(index, codePointOffset);
663     }
664 
665     /**
666      * Replaces the characters in the specified range with the contents of the
667      * specified string.
668      *
669      * @param start
670      *            the inclusive begin index.
671      * @param end
672      *            the exclusive end index.
673      * @param string
674      *            the string that will replace the contents in the range.
675      * @return this buffer.
676      * @throws StringIndexOutOfBoundsException
677      *             if {@code start} or {@code end} are negative, {@code start}
678      *             is greater than {@code end} or {@code end} is greater than
679      *             the length of {@code s}.
680      */
replace(int start, int end, String string)681     public synchronized StringBuffer replace(int start, int end, String string) {
682         replace0(start, end, string);
683         return this;
684     }
685 
686     /**
687      * Reverses the order of characters in this buffer.
688      *
689      * @return this buffer.
690      */
reverse()691     public synchronized StringBuffer reverse() {
692         reverse0();
693         return this;
694     }
695 
696     @Override
setCharAt(int index, char ch)697     public synchronized void setCharAt(int index, char ch) {
698         super.setCharAt(index, ch);
699     }
700 
701     @Override
setLength(int length)702     public synchronized void setLength(int length) {
703         super.setLength(length);
704     }
705 
706     @Override
subSequence(int start, int end)707     public synchronized CharSequence subSequence(int start, int end) {
708         return super.substring(start, end);
709     }
710 
711     @Override
substring(int start)712     public synchronized String substring(int start) {
713         return super.substring(start);
714     }
715 
716     @Override
substring(int start, int end)717     public synchronized String substring(int start, int end) {
718         return super.substring(start, end);
719     }
720 
721     @Override
toString()722     public synchronized String toString() {
723         return super.toString();
724     }
725 
726     @Override
trimToSize()727     public synchronized void trimToSize() {
728         super.trimToSize();
729     }
730 
writeObject(ObjectOutputStream out)731     private synchronized void writeObject(ObjectOutputStream out)
732             throws IOException {
733         ObjectOutputStream.PutField fields = out.putFields();
734         fields.put("count", length());
735         fields.put("shared", false);
736         fields.put("value", getValue());
737         out.writeFields();
738     }
739 
readObject(ObjectInputStream in)740     private void readObject(ObjectInputStream in) throws IOException,
741             ClassNotFoundException {
742         ObjectInputStream.GetField fields = in.readFields();
743         int count = fields.get("count", 0);
744         char[] value = (char[]) fields.get("value", null);
745         set(value, count);
746     }
747 }
748