NOTE
StringBuilder
1. What It Is: a mutable, thread-unsafe string. 2. Usage. 3. Implementation analysis: constructor, append, toString, and substring.
This is a historical learning note and may contain outdated or incomplete understanding.
1. What It Is
A mutable, thread-unsafe string.
Its implementation is somewhat similar to ArrayList: it uses a char array underneath, and it needs to expand when capacity is insufficient.
2. How to Use It
public class StringBuilderTest
{
public static void main(String[] args)
{
StringBuilder builder = new StringBuilder();
builder.append("test");
}
}
3. Implementation Analysis
3.1. Constructor
// Cannot be inherited; serializable
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
public StringBuilder() {
// Call the parent class (AbstractBuilder) constructor and initialize the capacity to 16
super(16);
}
}
// AbstractBuilder constructor
abstract class AbstractStringBuilder implements Appendable, CharSequence {
// Not modified with final, which means the reference can change
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
// Create a character array
value = new char[capacity];
}
3.2. append Method
Characters are appended directly to the internal char array.
If the capacity is insufficient, it needs to expand to twice the original capacity plus 2.
public StringBuilder append(String str) {
// Call the parent class's append method
super.append(str);
return this;
}
AbstractBuilder’sappendmethod
public AbstractStringBuilder append(String str) {
// If it is null, append the string "null"
if (str == null)
return appendNull();
// Capacity must also be sufficient
int len = str.length();
ensureCapacityInternal(count + len);
// String's getChars method. Check whether the parameters are valid, then call System.arraycopy to copy the array
str.getChars(0, len, value, count);
count += len;
return this;
}
private AbstractStringBuilder appendNull() {
int c = count;
// Ensure there is enough capacity for the original capacity + 4
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflowconscious code
// Subtraction is used to prevent overflow
if (minimumCapacity value.length > 0) {
value = Arrays.copyOf(value,
// Calculate the expanded capacity
newCapacity(minimumCapacity));
}
}
private int newCapacity(int minCapacity) {
// overflowconscious code
// Original capacity * 2 + 2
int newCapacity = (value.length << 1) + 2;
// If original capacity * 2 + 2 < the minimum required capacity, use the minimum required capacity
if (newCapacity minCapacity < 0) {
newCapacity = minCapacity;
}
// The calculated new capacity overflows or exceeds the maximum limit: private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE 8
return (newCapacity <= 0 || MAX_ARRAY_SIZE newCapacity < 0)
// Use the minimum required capacity instead
? hugeCapacity(minCapacity)
// Otherwise return it directly
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
// If the minimum required capacity exceeds the maximum integer value, throw OOM
if (Integer.MAX_VALUE minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
// Take either the minimum required capacity or the maximum limit
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
// String's getChars method
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd srcBegin);
}
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd srcBegin);
}
3.3. toString
public String toString() {
// Construct a String object directly
return new String(value, 0, count);
}
3.4. subString
public String substring(int start, int end) {
// Index out-of-bounds check
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
throw new StringIndexOutOfBoundsException(end);
if (start > end)
throw new StringIndexOutOfBoundsException(end start);
// Construct using String
return new String(value, start, end start);
}
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub