JDK1.8

An overview of the

Strings are immutable. Private final char value[]; To store each character in the string. The concat and subString methods of String are new to a new String object.

StringBuffer since JDK1.0, used to implement mutable strings. Stringbuffers are thread-safe, and most methods are embellished with the synchronized keyword. The two main methods of comparison in StringBuffer are append and INSERT.

The StringBuilder since JDK1.5. Used to implement mutable strings, but methods are not modified with the synchronized keyword, so thread-safe, but more efficient.

String

Constant pool

public static void main(String[] args) {
    String str = "ab";
    String str1 = "a" + "b";
    String str2 = new String("ab");
    String str3 = "ab".intern();
    String str4 = "a".intern() + "b".intern();
    String str5 = new String("ab").intern();
    System.out.println(str == str1); // true
    System.out.println(str == str2); // false
    System.out.println(str == str3); // true
    System.out.println(str == str4); // false
    System.out.println(str == str5); // true
}
Copy the code

The runtime constant pool is part of the method area, and string literals from the constant pool table in the Class file are stored in the runtime constant pool once the Class is loaded. The ones that use new will be allocated in the Java heap.

Intern ()

Returns a canonical representation of a string object.

A String pool, initially empty, maintained privately by the String class.

When the intern method is called, if the pool already contains a String equal to the String as determined by equals(Object), then the pool String is returned. Otherwise, the String is added to the pool and a reference to the String is returned.

It follows that for any two strings s and t, s.intern() == T.intern () is true if and only if S.quals (t) is true.

All literal strings and constant expressions of string values are intern. String literals are defined in section 3.10.5 of The Java™ language specification.

String#concat

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}
Copy the code

Array.copyof (char[], int) extends the length of an array and returns a new array of characters:

public static char[] copyOf(char[] original, int newLength) {
    char[] copy = new char[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
Copy the code

New a char of a new length [], then call system.arrayCopy () :

public static native void arraycopy(Object src,  int srcPos,
                                    Object dest, int destPos,
                                    int length);
Copy the code

SRC is a native method that copies the SRC from the srcPos position to the destPos of dest.

Above we copy the smaller values of the two lengths and get the new buf[]. Then call str.getchars (buf, len); :

void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}
Copy the code

The string to be added is copied to the position after len of buf[], which is the length of the string to be added.

Finally, a new string return is constructed with buf[] as an argument.

StringBuilder

field

AbstractStringBuilder:

char[] value; Stores characters in SB.

int count; The number already used in the value array.

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

A constructor

The initial capacity of SB is 16.

public StringBuilder(a) {
    super(16);
}
Copy the code

StringBuilder#append

@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}
Copy the code
public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
Copy the code

If null is passed in, convert to a string and insert it:

private AbstractStringBuilder appendNull(a) {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;
}
Copy the code

If the constructor passes NULL, the NPE is reported.

Enrecapacityinternal also adds length to Arrays. CopyOf:

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); }}Copy the code

The new length is usually twice the original length + 2:

private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)? hugeCapacity(minCapacity) : newCapacity; }Copy the code

Another overloaded method of String#getChars is then called:

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);
}
Copy the code

str.getChars(0, len, value, count); The value array of STR to be added is copied to SB’s value, after count, and is len-0 in length. STR was hooked up.

Let’s update the count already used by the value array in SB and return the updated SB.

StringBuilder#toString

@Override
public String toString(a) {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}
Copy the code

Construct a String from 0 to count of value in SB.

StringBuffer

Most methods are implemented in much the same way as StringBuilder.

Private TRANSIENT char[] toStringCache; Is used to cache the last value returned by toString, and null is set whenever SB changes it.

@Override
public synchronized String toString(a) {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}
Copy the code
public static char[] copyOfRange(char[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + ">" + to);
    char[] copy = new char[newLength];
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}
Copy the code

reference

The source code

Java String objects, do you really understand?