另一个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
定义为常量不是更好吗,因为它是线程安全的,而且我们知道它可以在编译时与加号运算符连接。像这样的东西:
private final static REALLY_LONG_QUERY1 = "A quite long query that"
+"doesn't fit in one line"
+"...";
最佳答案
Wouldn't it be better to define the String as a constant ...
基本上是的。
... since it would be thread safe and we know it can get concatenated at compile time with the plus operator.
这些断言都是正确的。
但是,您无需担心使用 StringBuffer
的代码版本中的任何线程安全性。
StringBuffer
类是线程安全的。- 如果
StringBuffer
实例仅对一个线程可见(例如,调用声明和使用该实例的方法的线程),则该实例线程受限并且不会不需要是线程安全的数据结构。 (你可以使用StringBuilder
代替......)
使用 +
文字连接的版本的主要优点是它在运行时花费零时间,并且不会导致对象分配......除了表示连接的一个 String 对象之外加载类时分配的字符串常量。
事实上,在许多地方人们明确使用 StringBuilder
或 StringBuffer
来“优化”字符串连接,它要么没有效果,或者实际上使代码变慢:
正如您所指出的,Java 编译器在编译时评估文字的串联(使用
+
),但它不能对显式StringBuilder.append< 执行相同的操作
调用。此外,Java 编译器通常会将表达式中的非常量字符串连接(使用
+
)转换为使用StringBuilder
的等效代码。
唯一值得显式使用 StringBuilder
的情况是当字符串构建跨越多个语句时;例如因为你正在循环中连接东西。
关于java - 文字的字符串分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15813099/