在Java中使用String或StringBuffer:哪个更好?

在Java中使用String或StringBuffer:哪个更好?,java,string,Java,String,我读了很多关于使用StringBuffer和String的书,特别是在Java中涉及连接的地方,以及它们是否是线程安全的 那么,在各种Java方法中,应该使用哪种方法呢 例如,在PreparedStatement中,查询应该是StringBuffer: String query = ("SELECT * " + "FROM User " + "WHERE userName = ?;"); try {

我读了很多关于使用StringBuffer和String的书,特别是在Java中涉及连接的地方,以及它们是否是线程安全的

那么,在各种Java方法中,应该使用哪种方法呢

例如,在PreparedStatement中,查询应该是StringBuffer:

    String query = ("SELECT * " +
                    "FROM User " +
                    "WHERE userName = ?;");

    try {
        ps = connection.prepareStatement(query);
然后,在字符串实用程序中,使用以下方法:

public static String prefixApostrophesWithBackslash(String stringIn) {
    String stringOut = stringIn.replaceAll("'", "\\\\'");
    return stringOut;
}
以及:

//从字符串中删除字符。
公共静态字符串removeChar(字符串stringIn,字符c){
字符串stringOut=(“”);
对于(int i=0;i
我应该使用StringBuffers吗?尤其是在RepalCell无论如何都不可用于此类对象的情况下

谢谢

摩根先生


谢谢你的建议。StringBuffers已经被StringBuilders所取代,而StringBuilders取代了我认为最好的字符串

几乎不需要使用
StringBuffer

而不是你可能指的
StringBuffer
。StringBuffer与StringBuilder类似,只是它还提供线程安全性。这种线程安全性在实践中很少需要,只会导致代码运行更慢


您的问题似乎不是关于String vs StringBuffer,而是关于使用内置方法或自己实现代码。如果有一个内置的方法可以完全满足您的需要,那么您可能应该使用它。很可能它比您编写的代码优化得更好。

下面的代码段

 // Removes a char from a String.
public static String removeChar(String stringIn, char c) {
    String stringOut = ("");
    for (int i = 0; i < stringIn.length(); i++) {
        if (stringIn.charAt(i) != c) {
            stringOut += stringIn.charAt(i);
        }
    }
    return stringOut;
}
//从字符串中删除字符。
公共静态字符串removeChar(字符串stringIn,字符c){
字符串stringOut=(“”);
对于(int i=0;i

您可以只执行
stringIn.replaceAll(c+“”,“”)
对于可以被视为单线程的情况,最好是。它不会增加任何同步开销,而StringBuffer会增加同步开销


只有当您懒于使用StringBuilder或只是想让代码易于阅读时,“+”运算符的字符串连接才是“好的”,并且从性能的角度来看,这是可以接受的,比如启动日志消息“log.info”(“+app_name的“Starting instance”+inst_id+);”

,即使在MT代码中,让多个线程将内容附加到字符串中是不常见的。StringBuilder几乎总是优于StringBuffer

没有简单的答案(除了重复
StringBuilder
StringBuffer
的咒语之外)。为了选择最有效的解决方案,您确实对“引擎盖下”发生的事情有了相当的了解

在第一个示例中,
String
是一种方法。Java编译器可以为由字符串串联序列组成的任何表达式生成非常优化的代码(如有必要,使用
StringBuilder
)。而且,如果连接的字符串都是常量或文本,编译器实际上可以在编译时进行连接

在第二个示例中,还不完全清楚是
String
还是
StringBuilder
更好。。。或者它们是否大致相等。我们需要查看
java.util.regex.Matcher
类的代码来解决这个问题

编辑-我查看了代码,实际上使用字符串或StringBuilder作为源代码没有什么区别。在内部,
Matcher.replaceAll
方法创建一个新的StringBuilder,并通过附加源字符串和替换字符串中的块来填充它


在第三个示例中,
StringBuilder
显然是最好的。当前一代Java编译器无法优化代码(如所写),以避免在添加每个字符时创建新字符串。

现代编译器已经优化了代码。因此,一些字符串添加将被优化以使用StringBuilder,如果我们认为可以增加可读性,我们可以保留字符串添加

示例1:

String query = ("SELECT * " +
                "FROM User " +
                "WHERE userName = ?;");
String numbers = "";
for (int i = 0;i < 20; i++)
  numbers = numbers + i;
将被优化为以下内容:

StringBuiler sb = new StringBuilder();
sb.append("SELECT * ");
sb.append("FROM User ");
sb.append("WHERE userName = ?;");
String query = sb.toString();
示例2:

String query = ("SELECT * " +
                "FROM User " +
                "WHERE userName = ?;");
String numbers = "";
for (int i = 0;i < 20; i++)
  numbers = numbers + i;
字符串编号=”;
对于(int i=0;i<20;i++)
数字=数字+i;
这无法优化,我们应该在代码中使用StringBuilder



我为SUN jdk1.5+做了这个观察。因此,对于较旧的Java版本或不同的JDK,可能会有所不同。在那里,它可以保存为始终编码StringBuilder(或jdk 1.4.2及更早版本的StringBuffer)。

我希望在第一个示例中,没有在内部使用StringBuilder,而编译器可以将字符串连接成一个字符串,因为没有可变性。但是考虑到这个PreparedStatement可以在多线程场景中使用,StringBuffer不是更好吗?@Morgan先生-您可以使用StringBuilder作为构建查询字符串的中间步骤,而这个局部变量不会被其他线程看到。因此,它不存在并发问题-不要简单地假设“多线程应用程序=>在任何地方都使用线程安全类”。实际上,在绝大多数情况下,编译器会将第二种形式转换为一系列StringBuilder调用。因此,通常情况下,最好对示例中给出的类型使用字符串连接,因为它更干净。您可以使用StringBuilder处理任何不直接连接在一起的内容;e、 在循环中,或者在函数调用之间传递生成器时。@Andrzej Doyle-实际上,我建议在我的示例中使用字符串连接。评论前请仔细阅读。是的,但你的第二段暗示性能较差。我的观点是,在大多数情况下(如果