When the compiler selects a StringBuffer over a StringBuilder to concatenate strings

I watched StringJavadoc when I noticed this bit about string concatenation:

The Java language provides special support for the string operator concatenation (+), and for converting other objects to strings. Concatenation Stringis through StringBuilder(or StringBuffer)

From Java 8 JLS 15.8.1 , this is a choice left to the compiler (emphasis mine):

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding the intermediate String object. To increase the performance of a repeating concatenation string, the Java compiler can use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluating the expression .

I made a small program to see that it compiles before

public class Tester {

    public static void main(String[] args) {
        System.out.println("hello");
        for (int i = 1; i < 5; i++) {
            String s = "hi " + i;
            System.out.println(s);
        }
        String t = "me";
        for (int i = 1; i < 5; i++) {
            t += i;
            System.out.println(t);
        }
        System.out.println(t);
    }
}

And the output at startup javap -c Testershows that it is used StringBuilder:

Compiled from "Tester.java"
public class Tester {
  public Tester();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String hello
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: iconst_1
       9: istore_1
      10: iload_1
      11: iconst_5
      12: if_icmpge     48
      15: new           #5                  // class java/lang/StringBuilder
      18: dup
      19: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
      22: ldc           #7                  // String hi
      24: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      27: iload_1
      28: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      31: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      34: astore_2
      35: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      38: aload_2
      39: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      42: iinc          1, 1
      45: goto          10
      48: ldc           #11                 // String me
      50: astore_1
      51: iconst_1
      52: istore_2
      53: iload_2
      54: iconst_5
      55: if_icmpge     90
      58: new           #5                  // class java/lang/StringBuilder
      61: dup
      62: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
      65: aload_1
      66: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      69: iload_2
      70: invokevirtual #9                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      73: invokevirtual #10                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      76: astore_1
      77: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      80: aload_1
      81: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      84: iinc          2, 1
      87: goto          53
      90: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      93: aload_1
      94: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      97: return
}

I examined a few questions telling a story, which is StringBuilderusually faster due to synchronization in StringBuffer, and this replaces these string concatenations:

, , , , StringBuilder, , :

  • StringBuffer StringBuilder?
  • , AbstractStringBuilder?
+4
2

, , . , Java 1.5 aka Java 5 StringBuilder. StringBuffer StringBuilder, , .

Java 5 StringBuilder, synchronized, String, . , 1.5 , ( - ), StringBuilder, StringBuffer 1.5 .

+5

(javac - ). StringBuffer StringBuilder . , StringBuffer .

, , / / StringBuffer.

+3

All Articles