在《阿里巴巴 Java 开发手册》的OOP规约第17条指出:在循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法而不是 " + "。具体如下:

【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。

反例:
String chenmo = "沉默";
String wanger = "王二";
String sum=chenmo+wanger;

上面的代码反编译:

String chenmo = "\u6C89\u9ED8"; // 沉默
String wanger = "\u738B\u4E8C"; // 王二
String sum=(newStringBuilder(String.valueOf(chenmo))).append(wanger).toString();

  通过反编译可得知:反编译出的字节码文件显示在使用"+"进行字符串连接时,每次都会 new 出一个 StringBuilder 对象,然后进行append 操作,最后通过 toString 方法返回 String 对象,这样不但使时间消耗增加,还造成内存资源浪费。
在java中,连接字符串常用的方式有以下几种:

  1.直接用“+”号
  2.使用String的方法concat
  3.使用StringBuilder的append
  4.使用StringBuffer的append
为了测试四种方法的性能,使用长度为10万的字符串进行测试。
图片说明
输入一个长度为100000的字符串,然后for循环每次取出长度为1的子串,添加到新字符串str1的末尾。测试代码如下:
(只保留核心代码)

public class 连接字符串 {

    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String str = sc.next();

    /*使用"+"连接*/
    String str1 = "";
    for (int i = 0; i < str.length(); i++) {
        str1 += str.substring(i, 1 + i);
    }

    /*StringBuilder的append方法连接*/
    StringBuilder str1 = new StringBuilder();
    long start = System.currentTimeMillis();
    for (int i = 0; i < str.length(); i++) {
        str1.append(str.substring(i, 1 + i));
    }

   /*使用String的concat方法连接*/
    String str1 = "";
    for (int i = 0; i < str.length(); i++) {
        str1 = str1.concat(String.valueOf(str.substring(i, 1 + i)));
    }

   /*StringBuffer的append方法连接*/
    StringBuffer str1 = new StringBuffer();
    for (int i = 0; i < str.length(); i++) {
        str1.append(str.substring(i, 1 + i));
    }

    }

}

测试结果:

 1.直接用“+”号

图片说明

 2.使用String的方法concat

图片说明

 3.使用StringBuffer的append

 4.使用StringBuilder的append

根据上面的分析和测试可以知道:

  • Java 中字符串拼接不要直接使用+拼接。
  • 在不需要考虑线程安全问题的时候,使用StringBuilder的效率比StringBuffer更高

注:StringUtils.join也可以用于字符串拼接,因为用的较少,所以未进行比较,据说性能与StringBuffer的append方法相差无几,比其要好。

关于 String 的其他最佳实践

  • 使用str != null && str.length() != 0来判断空串,效率比较高。

  • 在需要把其他对象转换为字符串对象时,使用String.valueOf(obj)而不是直接调用obj.toString()方法,因为前者已经对空值进行检测了,不会抛出空指针异常。

  • 使用String.format()方法对字符串进行格式化输出。

  • 对于较多的比较,使用switch代替if - else。(在 JDK 7 及以上版本,可以在switch结构中使用字符串了)