String, StringBuilder, StringBuffer source analysis

String source

  private final char value[];

    public String(a) {
        this.value = "".value;
    }

    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
Copy the code

As you can see from the graph, strings are composed of char arrays with the final keyword, which means that objects of type String cannot be changed.

String a = "abc";
a = a + "d";
System.out.println(a);
StringBuffer buffer = new StringBuffer();
buffer.append("a");
System.out.println(buffer);
StringBuilder builder = new StringBuilder();
builder.append("b");
System.out.println(builder);
Copy the code

The Java virtual machine creates a String a and assigns the value of “D” to the new String A. The Java virtual machine’s garbage collection (GC) collects the original A, so the String is not actually changed. As you can see, it is not recommended to use String for frequently manipulated strings. This is a slow process of constantly creating new objects and reclaiming old ones.

String + operation principle

public static void main(String[] args) {
   int num = 10;
   String a = "abc";
   long time = System.currentTimeMillis();
   String b = "hello world";
   for (int i = 0; i < num; i++) { a = a + b; System.out.println(a); }}Copy the code

In JDK9 and earlier, String + operations are implemented by building a StringBuilder object and calling the object’s append() method.

JDK11, decomcompiled:

// As of JDK 9, string concatenation operations are compiled to use the Invokedynamic directive. Java invokedynamic instruction using the boot method. Lang. Invoke. StringConcatFactory. MakeConcatWithConstants
// Use jDK11 to decompress the code
public static void main(final String[] args) {
        final int num = 10;
        String a = "abc";
        final long time = System.currentTimeMillis();
        for (int i = 0; i < num; ++i) { a = invokedynamic(makeConcatWithConstants:(Ljava/lang/String;) Ljava/lang/String; , a);// Notice hereSystem.out.println(a); }}Copy the code

StringBuffer source

public class StringBuffer extends AbstractStringBuilder{
    // char arrays hold characters
    char[] value;
    public StringBuffer(a) {
        // The default initial capacity is 16
        super(16); }}Copy the code

As you can see from the source code, the underlying StringBuffer is also a char array. StringBuffer default initial space is 16. For StringBuffer expansion, as you can see from the figure below, it’s twice the size of the old array, plus 2.

Let’s take a look at the append function of a StringBuffer, which is thread-safe and is modified by synchronized.

The StringBuilder source

A comparison with the source code for StringBuffer shows that the underlying array is also a char array, and the initial space is 16. Both StringBuilder and StringBuffer are derived from AbstractStringBuilder, so the initial space and expansion are the same.

public final class StringBuilder
    extends AbstractStringBuilder {
    // char arrays hold characters
    char[] value;
    public StringBuilder(a) {
        // The default initial capacity is 16
        super(16); }}Copy the code

The difference between StringBuilder and StringBuffer can be seen in the picture below. For the append() method, the lack of synchronized qualifiers makes StringBuilder not thread-safe.

conclusion

String length size immutable StringBuffer and StringBuilder Length variable StringBuffer thread safety StringBuilder thread safety therefore: String: Applicable to the situation of the small amount of string manipulation StringBuilder: is suitable for the single thread of the character buffer in a large number of operating StringBuffer: apply multithreading in character buffer under a large number of operating conditions