文字的字符串分配

时间:2013-04-04 13:45:43

标签: java string multithreading memory-management

另一个question回答了我如何在编译时评估字符串文字的连接。在我正在开发的项目中,我们使用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定义为常量不是更好,因为它是线程安全的,我们知道它可以在编译时与plus运算符连接。类似的东西:

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

4 个答案:

答案 0 :(得分:3)

  

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

基本上,是的。

  

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

这些断言都是正确的。

但是,您不需要担心StringBuffer代码版本中的线程安全问题。

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

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


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

  • 正如您所指出的,Java编译器在编译时评估文字的连接(使用+),但它不能对显式StringBuilder.append调用执行相同的操作。

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

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

答案 1 :(得分:1)

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

为什么呢?这是因为:

  • 更易阅读
  • 更多功能性(面向函数编程,时尚和高效)避免无用(临时)局部变量,尤其是可变变量(如buffer)。

答案 2 :(得分:0)

  

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

  

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

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

  

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

是的,这里更有意义。

答案 3 :(得分:0)

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

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

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