混淆:字符串是不可变的,所以不要用于连接

confusion : string is immutable so don't use for concatenation

JAVA :我想清除这样使用 String

String str = " SELECT "
           + "field1, "
           + "field2, "
           + "field3  "
           + " FROM table1; ";

可以使用这种方式。

根据关于 String 的最佳实践询问不要用于 concatenation

这是一个非常短的查询,但实际上我们有非常非常大的查询。这只是一个例子。所以只想确认我没有做错任何事。

String+ 运算符的连接在某些情况下可被视为不良做法,即如果它不能在编译时被 StringBuilder 调用自动替换.

一般来说,如果您的字段是常量或只初始化一次,那么 String+ 的串联就完全没问题了。

但是,如果您正在动态构建 String 并循环/递归,则最好使用 StringBuilder(或 StringBuffer 以实现线程安全连接)。

这没问题,和写成一个字符串完全一样:

String str = " SELECT field1, field2, field3   FROM table1; ";

如果您连接字符串文字,编译器将在编译时进行连接,因此生成的字节码是完全相同的,无论您是像以前那样编写还是作为一个字符串文字编写。

我非常怀疑 field1 和 field2 以及 table1 是预先知道的,我假设它们作为某些函数的参数出现。

在那种情况下,您应该改用 StringBuilder。即使你用加号连接,你仍然(几乎总是)得到一个 StringBuilder,只要看看字节码。这是一个参考:

"An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression." .15.18.1

请记住,如果循环,将会降低性能。

你的例子很好,因为它只涉及文字,编译器会在编译时进行连接。


但是如果你有:

String str = " SELECT "
           + "field1, "
           + someVariable
           + "field3  "
           + " FROM table1; ";

...那么编译器将只能为您处理其中的一部分,导致在运行时:

String str = " SELECT field1, "
           + someVariable
           + "field3   FROM table1; ";

它在运行时发生的方式是通过 StringBuilder,这听起来不错,但遗憾的是效率很低,实际上它是:

StringBuilder sb1 = new StringBuilder();
sb1.append(" SELECT field1, ");
sb1.append(someVariable);
String temp = sb1.toString();
StringBuilder sb2 = new StringBuilder();
sb2.append(temp);
sb2.append("field3   FROM table1; ");
String str = sb2.toString();

它不仅创建多个 StringBuilder 实例并对 toString 进行不必要的调用,而且它使用默认构造函数,它只为其数组中的 16 个字符的字符串分配足够的空间(最后我检查了)。因此 StringBuilder 可能不得不在 至少 处重新分配其内部数组一次。布莱赫,对吧? (等等...)

与你自己能做的比较:

String str = (new StringBuilder(200))
                .append(" SELECT " +
                        "field1, ")
                .append(someVariable)
                .append("field3  " +
                        " FROM table1; ")
                .toString();

效率更高。

但是更好吗?看起来很糟糕,维护起来也很糟糕。从性能的角度来看,您必须在紧密的循环中进行操作才能发挥作用。

因此,如果您有性能问题,这有助于解决,那就 "better"。

如果你不这样做就不是 "better",因为代码不太清楚。

None 如果您只处理文字,那么这很重要。

+ 在循环中连接字符串时被认为是错误的。假设您有

String s = "f";
for (int i=0; i<100; i++){
    s = s + "o";
}

在这种情况下

s = s + "o";

将被编译为

s = new StringBuilder(f).append("o").toString();

因此在每次迭代中您都在创建新的 StringBuilder,将 s 的当前内容复制到其中,然后添加 o 并通过调用 toString 重新创建新的 String 实例您存储在 s 参考中。如您所见,有很多事情要做,尤其是复制和创建 String 的新实例,执行时间取决于字符串的长度。

首选方法是创建您自己的 StringBuilder,在循环中附加您想要的内容,并在循环结束后从 StringBuilder 的内容创建新的 String 对象。像

StringBuilder sb = new StringBuilder("f");
for (int i=0; i<100; i++){
    sb.append("o");
}
String s = sb.toString();

但在你的情况下,因为你在编译时间常数上运行,它不能被改变,所以编译器能够弄清楚

String str = " SELECT "
           + "field1, "
           + "field2, "
           + "field3  "
           + " FROM table1; ";

只能是 " SELECT field1, field2, field3 FROM table1; " 所以它将在编译时连接起来所以你的 str 将被编译为

String str = " SELECT field1, field2, field3   FROM table1; ";

你在这里做的并没有错。但这很尴尬,原因如下:

  • 难以辨认:所有的运算符和引号都让人难以阅读

  • 容易出错:修改它时很容易从子字符串中省略 space 并中断查询

  • 不方便:您无法将查询复制到 SQL 工具中,而不必停止并删除所有运算符和引号。

您可以像这样将 SQL 提取到配置文件中,属性文件或 XML(使用 CDATA)都可以。您可以在 Spring Integration - Externalizing JDBC Queries

查看示例