我需要编写更长的查询,这些查询是动态生成的并附加在字符串变量中。众所周知,下面的代码会在每次执行+ =时生成不同的字符串变量实例。
String str = "";
str +="select * from";
str+=" users where userid = 1";
我想知道以下是否会做同样的事情或只是制作一个实例?
String str = "select * from "+" users where userid = 1";
答案 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是可行的方法,但也尝试在顶部使用重用的字符串常量,这样你就不会经常创建它们了。在循环中。