blob: 4387f3388a1d505afb47578b8769d49d6a964b6e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
/**
* A modifiable {@link CharSequence sequence of characters} for use in creating
* strings, where all accesses are synchronized. This class has mostly been replaced
* by {@link StringBuilder} because this synchronization is rarely useful. This
* class is mainly used to interact with legacy APIs that expose it.
*
* <p>For particularly complex string-building needs, consider {@link java.util.Formatter}.
*
* <p>The majority of the modification methods on this class return {@code
* this} so that method calls can be chained together. For example:
* {@code new StringBuffer("a").append("b").append("c").toString()}.
*
* @see CharSequence
* @see Appendable
* @see StringBuilder
* @see String
* @see String.format
* @since 1.0
*/
public final class StringBuffer extends AbstractStringBuilder implements
Appendable, Serializable, CharSequence {
private static final long serialVersionUID = 3388685877147921107L;
private static final ObjectStreamField serialPersistentFields[] = {
new ObjectStreamField("count", int.class),
new ObjectStreamField("shared", boolean.class),
new ObjectStreamField("value", char[].class), };
/**
* Constructs a new StringBuffer using the default capacity which is 16.
*/
public StringBuffer() {
super();
}
/**
* Constructs a new StringBuffer using the specified capacity.
*
* @param capacity
* the initial capacity.
*/
public StringBuffer(int capacity) {
super(capacity);
}
/**
* Constructs a new StringBuffer containing the characters in the specified
* string. The capacity of the new buffer will be the length of the
* {@code String} plus the default capacity.
*
* @param string
* the string content with which to initialize the new instance.
* @throws NullPointerException
* if {@code string} is {@code null}.
*/
public StringBuffer(String string) {
super(string);
}
/**
* Constructs a StringBuffer and initializes it with the content from the
* specified {@code CharSequence}. The capacity of the new buffer will be
* the length of the {@code CharSequence} plus the default capacity.
*
* @param cs
* the content to initialize the instance.
* @throws NullPointerException
* if {@code cs} is {@code null}.
* @since 1.5
*/
public StringBuffer(CharSequence cs) {
super(cs.toString());
}
/**
* Adds the string representation of the specified boolean to the end of
* this StringBuffer.
* <p>
* If the argument is {@code true} the string {@code "true"} is appended,
* otherwise the string {@code "false"} is appended.
*
* @param b
* the boolean to append.
* @return this StringBuffer.
* @see String#valueOf(boolean)
*/
public StringBuffer append(boolean b) {
return append(b ? "true" : "false");
}
/**
* Adds the specified character to the end of this buffer.
*
* @param ch
* the character to append.
* @return this StringBuffer.
* @see String#valueOf(char)
*/
public synchronized StringBuffer append(char ch) {
append0(ch);
return this;
}
/**
* Adds the string representation of the specified double to the end of this
* StringBuffer.
*
* @param d
* the double to append.
* @return this StringBuffer.
* @see String#valueOf(double)
*/
public StringBuffer append(double d) {
RealToString.getInstance().appendDouble(this, d);
return this;
}
/**
* Adds the string representation of the specified float to the end of this
* StringBuffer.
*
* @param f
* the float to append.
* @return this StringBuffer.
* @see String#valueOf(float)
*/
public StringBuffer append(float f) {
RealToString.getInstance().appendFloat(this, f);
return this;
}
/**
* Adds the string representation of the specified integer to the end of
* this StringBuffer.
*
* @param i
* the integer to append.
* @return this StringBuffer.
* @see String#valueOf(int)
*/
public StringBuffer append(int i) {
IntegralToString.appendInt(this, i);
return this;
}
/**
* Adds the string representation of the specified long to the end of this
* StringBuffer.
*
* @param l
* the long to append.
* @return this StringBuffer.
* @see String#valueOf(long)
*/
public StringBuffer append(long l) {
IntegralToString.appendLong(this, l);
return this;
}
/**
* Adds the string representation of the specified object to the end of this
* StringBuffer.
* <p>
* If the specified object is {@code null} the string {@code "null"} is
* appended, otherwise the objects {@code toString} is used to get its
* string representation.
*
* @param obj
* the object to append (may be null).
* @return this StringBuffer.
* @see String#valueOf(Object)
*/
public synchronized StringBuffer append(Object obj) {
if (obj == null) {
appendNull();
} else {
append0(obj.toString());
}
return this;
}
/**
* Adds the specified string to the end of this buffer.
* <p>
* If the specified string is {@code null} the string {@code "null"} is
* appended, otherwise the contents of the specified string is appended.
*
* @param string
* the string to append (may be null).
* @return this StringBuffer.
*/
public synchronized StringBuffer append(String string) {
append0(string);
return this;
}
/**
* Adds the specified StringBuffer to the end of this buffer.
* <p>
* If the specified StringBuffer is {@code null} the string {@code "null"}
* is appended, otherwise the contents of the specified StringBuffer is
* appended.
*
* @param sb
* the StringBuffer to append (may be null).
* @return this StringBuffer.
*
* @since 1.4
*/
public synchronized StringBuffer append(StringBuffer sb) {
if (sb == null) {
appendNull();
} else {
synchronized (sb) {
append0(sb.getValue(), 0, sb.length());
}
}
return this;
}
/**
* Adds the character array to the end of this buffer.
*
* @param chars
* the character array to append.
* @return this StringBuffer.
* @throws NullPointerException
* if {@code chars} is {@code null}.
*/
public synchronized StringBuffer append(char[] chars) {
append0(chars);
return this;
}
/**
* Adds the specified sequence of characters to the end of this buffer.
*
* @param chars
* the character array to append.
* @param start
* the starting offset.
* @param length
* the number of characters.
* @return this StringBuffer.
* @throws ArrayIndexOutOfBoundsException
* if {@code length < 0} , {@code start < 0} or {@code start +
* length > chars.length}.
* @throws NullPointerException
* if {@code chars} is {@code null}.
*/
public synchronized StringBuffer append(char[] chars, int start, int length) {
append0(chars, start, length);
return this;
}
/**
* Appends the specified CharSequence to this buffer.
* <p>
* If the specified CharSequence is {@code null} the string {@code "null"}
* is appended, otherwise the contents of the specified CharSequence is
* appended.
*
* @param s
* the CharSequence to append.
* @return this StringBuffer.
* @since 1.5
*/
public synchronized StringBuffer append(CharSequence s) {
if (s == null) {
appendNull();
} else {
append0(s, 0, s.length());
}
return this;
}
/**
* Appends the specified subsequence of the CharSequence to this buffer.
* <p>
* If the specified CharSequence is {@code null}, then the string {@code
* "null"} is used to extract a subsequence.
*
* @param s
* the CharSequence to append.
* @param start
* the inclusive start index.
* @param end
* the exclusive end index.
* @return this StringBuffer.
* @throws IndexOutOfBoundsException
* if {@code start} or {@code end} are negative, {@code start}
* is greater than {@code end} or {@code end} is greater than
* the length of {@code s}.
* @since 1.5
*/
public synchronized StringBuffer append(CharSequence s, int start, int end) {
append0(s, start, end);
return this;
}
/**
* Appends the string representation of the specified Unicode code point to
* the end of this buffer.
* <p>
* The code point is converted to a {@code char[]} as defined by
* {@link Character#toChars(int)}.
*
* @param codePoint
* the Unicode code point to encode and append.
* @return this StringBuffer.
* @see Character#toChars(int)
* @since 1.5
*/
public StringBuffer appendCodePoint(int codePoint) {
return append(Character.toChars(codePoint));
}
@Override
public synchronized char charAt(int index) {
return super.charAt(index);
}
@Override
public synchronized int codePointAt(int index) {
return super.codePointAt(index);
}
@Override
public synchronized int codePointBefore(int index) {
return super.codePointBefore(index);
}
@Override
public synchronized int codePointCount(int beginIndex, int endIndex) {
return super.codePointCount(beginIndex, endIndex);
}
/**
* Deletes a range of characters.
*
* @param start
* the offset of the first character.
* @param end
* the offset one past the last character.
* @return this StringBuffer.
* @throws StringIndexOutOfBoundsException
* if {@code start < 0}, {@code start > end} or {@code end >
* length()}.
*/
public synchronized StringBuffer delete(int start, int end) {
delete0(start, end);
return this;
}
/**
* Deletes the character at the specified offset.
*
* @param location
* the offset of the character to delete.
* @return this StringBuffer.
* @throws StringIndexOutOfBoundsException
* if {@code location < 0} or {@code location >= length()}
*/
public synchronized StringBuffer deleteCharAt(int location) {
deleteCharAt0(location);
return this;
}
@Override
public synchronized void ensureCapacity(int min) {
super.ensureCapacity(min);
}
/**
* Copies the requested sequence of characters to the {@code char[]} passed
* starting at {@code idx}.
*
* @param start
* the starting offset of characters to copy.
* @param end
* the ending offset of characters to copy.
* @param buffer
* the destination character array.
* @param idx
* the starting offset in the character array.
* @throws IndexOutOfBoundsException
* if {@code start < 0}, {@code end > length()}, {@code start >
* end}, {@code index < 0}, {@code end - start > buffer.length -
* index}
*/
@Override
public synchronized void getChars(int start, int end, char[] buffer, int idx) {
super.getChars(start, end, buffer, idx);
}
@Override
public synchronized int indexOf(String subString, int start) {
return super.indexOf(subString, start);
}
/**
* Inserts the character into this buffer at the specified offset.
*
* @param index
* the index at which to insert.
* @param ch
* the character to insert.
* @return this buffer.
* @throws ArrayIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public synchronized StringBuffer insert(int index, char ch) {
insert0(index, ch);
return this;
}
/**
* Inserts the string representation of the specified boolean into this
* buffer at the specified offset.
*
* @param index
* the index at which to insert.
* @param b
* the boolean to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, boolean b) {
return insert(index, b ? "true" : "false");
}
/**
* Inserts the string representation of the specified integer into this
* buffer at the specified offset.
*
* @param index
* the index at which to insert.
* @param i
* the integer to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, int i) {
return insert(index, Integer.toString(i));
}
/**
* Inserts the string representation of the specified long into this buffer
* at the specified offset.
*
* @param index
* the index at which to insert.
* @param l
* the long to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, long l) {
return insert(index, Long.toString(l));
}
/**
* Inserts the string representation of the specified into this buffer
* double at the specified offset.
*
* @param index
* the index at which to insert.
* @param d
* the double to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, double d) {
return insert(index, Double.toString(d));
}
/**
* Inserts the string representation of the specified float into this buffer
* at the specified offset.
*
* @param index
* the index at which to insert.
* @param f
* the float to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, float f) {
return insert(index, Float.toString(f));
}
/**
* Inserts the string representation of the specified object into this
* buffer at the specified offset.
* <p>
* If the specified object is {@code null}, the string {@code "null"} is
* inserted, otherwise the objects {@code toString} method is used to get
* its string representation.
*
* @param index
* the index at which to insert.
* @param obj
* the object to insert (may be null).
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public StringBuffer insert(int index, Object obj) {
return insert(index, obj == null ? "null" : obj.toString());
}
/**
* Inserts the string into this buffer at the specified offset.
* <p>
* If the specified string is {@code null}, the string {@code "null"} is
* inserted, otherwise the contents of the string is inserted.
*
* @param index
* the index at which to insert.
* @param string
* the string to insert (may be null).
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
*/
public synchronized StringBuffer insert(int index, String string) {
insert0(index, string);
return this;
}
/**
* Inserts the character array into this buffer at the specified offset.
*
* @param index
* the index at which to insert.
* @param chars
* the character array to insert.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
* @throws NullPointerException
* if {@code chars} is {@code null}.
*/
public synchronized StringBuffer insert(int index, char[] chars) {
insert0(index, chars);
return this;
}
/**
* Inserts the specified subsequence of characters into this buffer at the
* specified index.
*
* @param index
* the index at which to insert.
* @param chars
* the character array to insert.
* @param start
* the starting offset.
* @param length
* the number of characters.
* @return this buffer.
* @throws NullPointerException
* if {@code chars} is {@code null}.
* @throws StringIndexOutOfBoundsException
* if {@code length < 0}, {@code start < 0}, {@code start +
* length > chars.length}, {@code index < 0} or {@code index >
* length()}
*/
public synchronized StringBuffer insert(int index, char[] chars, int start,
int length) {
insert0(index, chars, start, length);
return this;
}
/**
* Inserts the specified CharSequence into this buffer at the specified
* index.
* <p>
* If the specified CharSequence is {@code null}, the string {@code "null"}
* is inserted, otherwise the contents of the CharSequence.
*
* @param index
* The index at which to insert.
* @param s
* The char sequence to insert.
* @return this buffer.
* @throws IndexOutOfBoundsException
* if {@code index < 0} or {@code index > length()}.
* @since 1.5
*/
public synchronized StringBuffer insert(int index, CharSequence s) {
insert0(index, s == null ? "null" : s.toString());
return this;
}
/**
* Inserts the specified subsequence into this buffer at the specified
* index.
* <p>
* If the specified CharSequence is {@code null}, the string {@code "null"}
* is inserted, otherwise the contents of the CharSequence.
*
* @param index
* The index at which to insert.
* @param s
* The char sequence to insert.
* @param start
* The inclusive start index in the char sequence.
* @param end
* The exclusive end index in the char sequence.
* @return this buffer.
* @throws IndexOutOfBoundsException
* if {@code index} is negative or greater than the current
* length, {@code start} or {@code end} are negative, {@code
* start} is greater than {@code end} or {@code end} is greater
* than the length of {@code s}.
* @since 1.5
*/
public synchronized StringBuffer insert(int index, CharSequence s,
int start, int end) {
insert0(index, s, start, end);
return this;
}
@Override
public synchronized int lastIndexOf(String subString, int start) {
return super.lastIndexOf(subString, start);
}
@Override
public synchronized int offsetByCodePoints(int index, int codePointOffset) {
return super.offsetByCodePoints(index, codePointOffset);
}
/**
* Replaces the characters in the specified range with the contents of the
* specified string.
*
* @param start
* the inclusive begin index.
* @param end
* the exclusive end index.
* @param string
* the string that will replace the contents in the range.
* @return this buffer.
* @throws StringIndexOutOfBoundsException
* if {@code start} or {@code end} are negative, {@code start}
* is greater than {@code end} or {@code end} is greater than
* the length of {@code s}.
*/
public synchronized StringBuffer replace(int start, int end, String string) {
replace0(start, end, string);
return this;
}
/**
* Reverses the order of characters in this buffer.
*
* @return this buffer.
*/
public synchronized StringBuffer reverse() {
reverse0();
return this;
}
@Override
public synchronized void setCharAt(int index, char ch) {
super.setCharAt(index, ch);
}
@Override
public synchronized void setLength(int length) {
super.setLength(length);
}
@Override
public synchronized CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String substring(int start) {
return super.substring(start);
}
@Override
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
@Override
public synchronized String toString() {
return super.toString();
}
@Override
public synchronized void trimToSize() {
super.trimToSize();
}
private synchronized void writeObject(ObjectOutputStream out)
throws IOException {
ObjectOutputStream.PutField fields = out.putFields();
fields.put("count", length());
fields.put("shared", false);
fields.put("value", getValue());
out.writeFields();
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
ObjectInputStream.GetField fields = in.readFields();
int count = fields.get("count", 0);
char[] value = (char[]) fields.get("value", null);
set(value, count);
}
}