0

另一个问题回答了我如何在编译时评估字符串文字的连接。在我正在处理的一个项目中,我们使用StringBuffer. 它只附加文字,所以它让我思考是否会发生类似的事情。

在下面的代码中,缓冲区是否会在编译时附加其内容?当多个线程试图执行此函数时,这将如何表现?

 public static String querySomething(int arg){


        StringBuffer buffer = new StringBuffer();
        buffer.append("A quite long query");
        buffer.append("that doesn't fit in one line");
        buffer.append("...");

  }

将 定义为常量不是更好吗,String因为它是线程安全的,而且我们知道它可以在编译时与加号运算符连接起来。就像是:

  private final static REALLY_LONG_QUERY1 = "A quite long query that"
                                            +"doesn't fit in one line"
                                            +"...";
4

4 回答 4

3

将 String 定义为常量不是更好吗...

基本上,是的。

...因为它是线程安全的,而且我们知道它可以在编译时与加号运算符连接起来。

这些断言都是正确的。

但是,您无需担心带有StringBuffer.

  • 该类StringBuffer是线程安全的。
  • 如果StringBuffer实例仅对一个线程可见(例如,调用声明和使用实例的方法的线程),则实例是线程受限的,不需要是线程安全的数据结构。(你可以StringBuilder改用......)

使用文字连接的版本的主要优点+是它在运行时花费零时间,并且不会导致对象分配……除了一个 String 对象,它表示在加载类时分配的连接字符串常量。


事实上,在人们明确使用或“优化”字符串连接的许多地方,它要么没有效果,要么实际上使代码变慢:StringBuilderStringBuffer

  • 正如您所指出的,Java 编译器在编译器时评估文字的串联(使用+),但它不能为显式StringBuilder.append调用做同样的事情。

  • 此外,Java 编译器通常会将+表达式中的非常量字符串连接(使用 )转换为使用 的等效代码StringBuilder

唯一值得StringBuilder显式使用的情况是当刺构建跨越多个语句时;例如因为你在一个循环中连接东西。

于 2013-04-04T13:49:16.293 回答
1

我更喜欢第二种解决方案(仅使用+运算符)。

为什么?因为:

  • 更具可读性
  • 更多功能(面向函数式编程,当今时尚和高效)避免无用(临时)局部变量,尤其是可变变量(如bufferis)。
于 2013-04-04T13:53:59.030 回答
0

在下面的代码中,缓冲区是否会在编译时附加其内容?

是的。

当多个线程试图执行此函数时,这将如何表现?

没问题,因为每个线程都会使用它自己的StringBuffer(它在方法中声明)。

将 String 定义为常量不是更好吗?

是的,这里会更有意义。

于 2013-04-04T13:48:30.663 回答
0

当您想要构建一个在编译时不知道实际大小的字符串时,StringBuffer 更适合,例如:

public static String querySomething(int arg) {
    StringBuffer buffer = new StringBuffer();
    while (...) {
       buffer.Append(someStuff());
    }
}

在您的情况下,常数更合适。

于 2013-04-04T13:54:24.233 回答