另一个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"
+"...";
答案 0 :(得分:3)
将String定义为常量不是更好......
基本上,是的。
...因为它是线程安全的,我们知道它可以在编译时与plus运算符连接。
这些断言都是正确的。
但是,您不需要担心StringBuffer
代码版本中的线程安全问题。
StringBuffer
类是线程安全的。StringBuffer
实例仅对一个线程可见(例如,调用声明并使用该实例的方法的线程),则该实例线程受限并且不需要是一个线程安全的数据结构。 (您可以使用StringBuilder
代替......)使用+
文字串联的版本的主要优点是它在运行时花费零时间,并且不会导致对象的分配...除了表示连接字符串常量的一个String对象之外在你的班级加载时分配。
事实上,在许多地方,人们明确使用StringBuilder
或StringBuffer
来“优化”字符串连接,它要么没有效果,要么实际上使代码变慢:
正如您所指出的,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());
}
}
在你的情况下,常数更合适。