【问题标题】:What happens when Java Compiler sees many String concatenations in one line?当 Java 编译器在一行中看到许多字符串连接时会发生什么?
【发布时间】:2010-11-20 18:15:20
【问题描述】:

假设我在 Java 中有一个表达式,例如:

String s = "abc" + methodReturningAString() + "ghi" + 
                anotherMethodReturningAString() + "omn" + "blablabla";

Java 的默认 JDK 编译器的行为是什么?它只是进行五个连接还是完成了一个聪明的性能技巧?

【问题讨论】:

    标签: java performance string concatenation


    【解决方案1】:

    它生成等价于:

    String s = new StringBuilder("abc")
               .append(methodReturningAString())
               .append("ghi")
               .append(anotherMethodReturningAString())
               .append("omn")
               .append("blablabla")
               .toString();
    

    预连接静态字符串(即"omn" + "blablabla")非常聪明。如果您愿意,您可以将StringBuilder 的使用称为“性能技巧”。这绝对比执行五个连接导致四个不必要的临时字符串更好。此外,使用 StringBuilder 是(我认为)Java 5 的性能改进;在此之前,使用的是 StringBuffer。

    编辑:正如 cmets 中所指出的,静态字符串仅在它们位于连接的开头时才被预先连接。否则会破坏操作顺序(尽管在这种情况下,我认为 Sun 可以证明这一点)。因此,鉴于此:

    String s = "abc" + "def" + foo() + "uvw" + "xyz";
    

    它会这样编译:

    String s = new StringBuilder("abcdef")
               .append(foo())
               .append("uvw")
               .append("xyz")
               .toString();
    

    【讨论】:

    • +1。我看到了 StringBuilder 并准备发布澄清,直到我深入了解并发现您已经处理了它。
    • 是的,我不记得哪个是正确的,在我最初的修订后必须查找它
    • @Kip:并非相反,但我用 Sun 的 javac 1.6.0_15 编译了代码,并通过 jad(和 javap)运行了 .class,它实际上编译为:String s = (new StringBuilder()). append("abc"). append(methodReturningAString()). append("ghi"). append(anotherMethodReturningAString()). append("omn"). append("blablabla"). toString(); 它看起来像在这种情况下,Sun 编译器不够聪明,无法预先连接静态字符串。
    • @Kip:我使用 IBM RAD 内置的编译器(基于 Eclipse)编译了相同的代码,它编译为:String s = (new StringBuilder("abc")). append(methodReturningAString()). append("ghi"). append(anotherMethodReturningAString()). append("omn"). append("blablabla"). toString();,它仍然错过了文字字符串优化,但至少创建了 @ 987654328@ 与第一个 append()able 字符串。
    • 这与聪明与否无关。 Java 语言规范对求值顺序有非常具体的规则,即当运算符的优先级相同时,它必须是从左到右的。所以,虽然 "foo" + "bar" + baz 确实变成了 new StringBuilder("foobar").append(baz),但是 foo + "bar" + "baz" 不能编译成 new StringBuilder().append(foo)。 append("barbaz") 不破坏评估顺序规则。
    猜你喜欢
    • 2010-11-14
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2016-11-11
    相关资源
    最近更新 更多