什么时候引入Javac StringBuilder / StringBuffer优化?

时间:2017-02-27 14:15:13

标签: java javac stringbuilder stringbuffer jdk1.4

我知道Javac编译器能够使用+ / StringBuilder转换字符串连接StringBuffer,我很想知道从哪个版本开始引入了这个变化吗?

我正在使用此示例代码:

public class Main {
  public static void main(String[] args) {
      String a = args[0];
      String s = "a";
      s = s + a;
      s = s + "b";
      s = s + "c";
      s = s + "d";
      s = s + "e";
      System.out.println(s);
  }
}

到目前为止,我已尝试使用javac 1.8.0_121javac 1.6.0_20javac 1.5.0_22java 1.4.2_19

以下是我在javap -c使用1.4.2_19时看到的字节码示例:

6:  astore_2
7:  new #3; //class StringBuffer
10: dup
11: invokespecial   #4; //Method java/lang/StringBuffer."<init>":()V
14: aload_2
15: invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
18: aload_1
19: invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual   #6; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;

所有4个版本似乎都在使用StringBuilder / StringBuffer优化,所以我很想知道从哪个Javac版本开始引入了这个更改?

4 个答案:

答案 0 :(得分:31)

以下是language specification from version 1

的引用
  

实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间String对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类(第20.13节)或类似技术来减少通过表达式求值创建的中间String对象的数量。

当时回来,他们有StringBuffer而不是StringBuilder

还引用了JDK1.0.2的StringBuffer

  

此类是字符的可扩展缓冲区。它主要用于创建字符串。编译器使用它来实现“+”运算符。

答案 1 :(得分:11)

我查阅了Java语言规范,第一版(从1996年开始)。不容易找到,但是here it is。连接优化的过程即便如此:

  

实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间String对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer类(第20.13节)或类似技术来减少通过表达式求值创建的中间String对象的数量。

该规范当时属于StringBuffer,但StringBuilder(当前JLS措辞所指的)可能被视为性能更好,因为其方法不同步。

然而,这并不意味着人们应该依赖优化,因为总是到位。例如,循环中的字符串连接不会得到优化。

答案 2 :(得分:5)

JLS已经在一些答案中给出了。我只是想说明StringBuffer(https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html)是从1.0开始的,而

StringBuilder(https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)来自1.5版本。请参阅相应javadoc的since:部分。

答案 3 :(得分:5)

这不回答问题,但我只想补充一点,即在jdk-9中int允许的策略之一,但不是默认值。

StringBuilder::append

它实际上是字符串连接的private enum Strategy { /** * Bytecode generator, calling into {@link java.lang.StringBuilder}. */ BC_SB, /** * Bytecode generator, calling into {@link java.lang.StringBuilder}; * but trying to estimate the required storage. */ BC_SB_SIZED, /** * Bytecode generator, calling into {@link java.lang.StringBuilder}; * but computing the required storage exactly. */ BC_SB_SIZED_EXACT, /** * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}. * This strategy also tries to estimate the required storage. */ MH_SB_SIZED, /** * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}. * This strategy also estimate the required storage exactly. */ MH_SB_SIZED_EXACT, /** * MethodHandle-based generator, that constructs its own byte[] array from * the arguments. It computes the required storage exactly. */ MH_INLINE_SIZED_EXACT } 字节码,因此它的实现现在是JRE特定的,而不是编译器。默认策略btw是:invokedynamic