首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >字符串连接是否经过优化以使用现有的StringBuilders?

字符串连接是否经过优化以使用现有的StringBuilders?
EN

Stack Overflow用户
提问于 2017-07-26 02:45:58
回答 3查看 3.1K关注 0票数 23

我有以下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
StringBuilder str = new StringBuilder("foo");
for(Field f : fields){
    str.append("|" + f);
}
str.append("|" + bar);
String result = str.toString();

我知道编译器将优化字符串连接"|" + f,并将其替换为StringBuilder。但是,将创建一个新的StringBuilder,还是在Java8中使用现有的str?Java 9怎么样?

EN

回答 3

Stack Overflow用户

发布于 2017-07-26 02:57:40

默认情况下,java-9中没有用于字符串连接的StringBuilder;这是一个运行时决定如何通过invokedynamic进行连接。默认策略不是StringBuilder::append策略。

您还可以阅读更多的here

在java-8下,将创建一个新的字节码(非常容易发现invokespecial // Method java/lang/StringBuilder."<init>":()V在已编译的字节码中出现的两个地方)。

另外,您也有关于append.append...的建议;请注意,这比sb.append ... sb.append好得多,而here就是其中的原因。

票数 23
EN

Stack Overflow用户

发布于 2017-07-26 03:10:10

当字符串连接优化由Java编译器执行时,您可以通过解压缩字节代码来了解它所做的事情:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ cat Test.java
interface Field {}

public class Test {

    static String toString(Field[] fields, Object bar) {
        StringBuilder str = new StringBuilder("foo");
        for(Field f : fields){
            str.append("|" + f);
        }
        str.append("|" + bar);
        return str.toString();
    }
}
$ javac Test.java
$ javap -c Test.class
Compiled from "Test.java"
public class stackoverflow.Test {
  public stackoverflow.Test();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  static java.lang.String toString(stackoverflow.Field[], java.lang.Object);
    Code:
       0: new           #16                 // class java/lang/StringBuilder
       3: dup
       4: ldc           #18                 // String foo
       6: invokespecial #20                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
       9: astore_2
      10: aload_0
      11: dup
      12: astore        6
      14: arraylength
      15: istore        5
      17: iconst_0
      18: istore        4
      20: goto          53
      23: aload         6
      25: iload         4
      27: aaload
      28: astore_3
      29: aload_2
      30: new           #16                 // class java/lang/StringBuilder
      33: dup
      34: ldc           #23                 // String |
      36: invokespecial #20                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
      39: aload_3
      40: invokevirtual #25                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      43: invokevirtual #29                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      46: invokevirtual #32                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      49: pop
      50: iinc          4, 1
      53: iload         4
      55: iload         5
      57: if_icmplt     23
      60: aload_2
      61: new           #16                 // class java/lang/StringBuilder
      64: dup
      65: ldc           #23                 // String |
      67: invokespecial #20                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
      70: aload_1
      71: invokevirtual #25                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      74: invokevirtual #29                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      77: invokevirtual #32                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      80: pop
      81: aload_2
      82: invokevirtual #29                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      85: areturn
}

如您所见,代码在StringBuilder 3 places中调用构造函数(Method java/lang/StringBuilder."<init>":),因此将在每次迭代中创建新的StringBuilders (除非实时编译器执行奇特的优化)。

这不太可能是一个显著的性能问题,但在不太可能的情况下,您可以很容易地通过重写到

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
str.append("|").append(f);
票数 8
EN

Stack Overflow用户

发布于 2017-07-26 03:32:35

根据Java9API文档

实现注意事项: 只要编译器最终符合Java规范,字符串连接操作符的实现将由Java编译器自行决定。例如,javac编译器可能使用StringBuffer、StringBuilder或java.lang.invoke.StringConcatFactory实现操作符,这取决于JDK版本。字符串转换的实现通常是通过toString方法实现的,该方法由对象定义,并由Java的所有类继承。

根据这一点,它将在每次迭代时创建一个新的字符串生成器。因此,正如这里的几个人所提到的,使用下面的代码是更优化的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
append("|").append(f)

您可以找到API文档here

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45324692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文