在java中,String字符串拼接 concat方法 和字符串间直接用“+”号拼接的区别?

#在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.

猜你喜欢

转载自blog.csdn.net/ted_cs/article/details/82589068