在java字符串的情况下,+ =和s1 + s2之间的差异

时间:2015-09-29 11:40:18

标签: java string concatenation

我需要编写更长的查询,这些查询是动态生成的并附加在字符串变量中。众所周知,下面的代码会在每次执行+ =时生成不同的字符串变量实例。

String str = "";

  str +="select * from";
  str+=" users where userid = 1";

我想知道以下是否会做同样的事情或只是制作一个实例?

String str = "select * from "+" users where userid = 1";

4 个答案:

答案 0 :(得分:3)

如果只有文字,编译器可能会对其进行优化,但如果不是,则对字符串的每个+操作都会创建一个中间实例。实际上a += b只是写a = a + b的一种简短方式,对编译器来说也是一样。

顺便说一下,我有一种强烈的感觉,你想要将值连接到查询中。如果您可以请避免,因为它可能会引入严重的安全问题(SQL注入)。请改用PreparedStatement

答案 1 :(得分:2)

两个实例都会创建多个字符串。

如果您需要构建您的查询字符串,只需使用StringBuilder

StringBuilder query = new StringBuilder()
query.append("select * from ");
query.append(" users where userid = 1");

为了完整起见,如果您自己构建SQL查询,请查看Prepared Statements

答案 2 :(得分:2)

从语义角度来看,s += s1;s = s + s1;是完全相同的。

JLS 15.26.2。表示:

  

“形式E1 op = E2的复合赋值表达式等效于E1 =(T)((E1)op(E2)),其中T是E1的类型,除了E1仅被评估一次。”

在这种情况下:

   s += s1;

变为

   s = (String) ((s) + (s1));

变为

   s = s + s1;

删除冗余的类型转换和括号时。

但是你的例子(而不是问题标题)是关于String>> literals<<。对于String文字,我们必须考虑常量表达式规则。如果常量表达式满足JLS 15.28中设置的某些条件,则将在编译时对其进行求值。在您的示例中:

    "select * from " + " users where userid = 1";

是一个常量表达式,但涉及简单或复合赋值运算符的任何表达式都不是常量表达式。

事实上,JLS 15.18.1说明了这一点(关于String +运算符):

  

“String对象是新创建的(第12.5节),除非表达式是常量表达式(第15.28节)。”

因此,每次为特定示例执行语句时,在运行时创建的对象数量都会有所不同。第一个版本每次执行时都会创建两个新字符串,第二个版本将创建零个新字符串。

(JLS允许JIT编译器在+=版本中优化掉连接,并且字节码编译器不会在另一个版本中优化+。版本)。

答案 3 :(得分:0)

您需要在构建查询时备份和使用预准备语句,否则您可能会受到SQL注入攻击。

话虽如此,使用StringBuilder是可行的方法,但也尝试在顶部使用重用的字符串常量,这样你就不会经常创建它们了。在循环中。