#在java中,String字符串拼接 concat方法 和字符串间直接用“+”号拼接的区别?
转载至 https://www.2cto.com/kf/201301/180600.html
当我查看String类的concat函数的源码时,发现字符串连接是这么实现的:
Java代码:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
那么,字符串的连接符(+)的实现和这个有什么区别呢?如果有区别的话,那它是如何实现的呢?
此外,这两者分别在什么场合使用,有没有性能上的差异。
为了回答这个问题,我们可以做一个测试。
首先,我们连接两个字符串
Java代码:
String s = "foo";
String s1 = "bar";
String s2 = s+ s1;
下面我们将这个代码编译成class文件,然后再反编译(可以用JAD),我们得到反编译后的代码是:
Java代码:
String s = "foo";
String s1 = "bar";
String s2 = (new StringBuilder()).append(s).append(s1).toString();
所以,+ 和 concat 肯定是有区别的。
在性能上,从 concat() 源码可以看出,StringBuilder创建了更多的对象,而concat却没有,它使用的String类的内部实现。
综上,当我们需要连接两个字符串的时候,我们应当优先考虑使用 concat() 函数,当我们需要连接字符串和其它类型的变量时,再考虑使用+运算符。
译者注:用 javap -c 查看java生成的字节码:
Java代码:
java.lang.String cat(java.lang.String, java.lang.String);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: aload_1
8: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
11: aload_2
12: invokevirtual #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: invokevirtual #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
18: astore_1
19: aload_1
20: areturn
可以看出 a += b 其实等价于
Java代码:
a = new StringBuilder()
.append(a)
.append(b)
.toString();
Ted总结
通过以上可以看出,不管是用concat方法还是直接用+对字符串进行拼接,都会生成新对象。
引申思考:
public static void main(String[] args) {
String a = "Hello" ;
String b = "Word" ;
String c= a+b;
String str4 = "a" + "b";
System.out.println(c=="HelloWord");
System.out.println(str4 == "ab");
System.out.println(c.equals("HelloWord"));
}
会是什么结果呢?
false
true
true
分析:
① String c =a+b,它的实现过程其实是使用new StringBuilder()在堆中开辟了空间,最后调用to String方法转换为String对象,而"HelloWord"实际存储在常量池中,它们之间用==作对比(==是对引用地址值比较 ),肯定不相当。
② String str4 = “a” + “b”;根据编译器合并已知量的优化功能,池中开辟一块空间,存放合并后的String常量"ab",引用str4指向池中常量"ab",所以输出true
③c.equals(“HelloWord”)String里重写了equals方法,比较的的字符串的值是否相等,此时结果为true.