前言
据我所知字符串确实已经成为 Java 开发人员最常用的类了,而且是大量使用。我们都知道,String 其实是封装了字符,所以俩字符串连接就是将字符串对象里面的字符连起来。很多人习惯使用+
来连接字符串,也有人会用 StringBuilder 的append
方法。
“+”编译后
看看如果我们在程序中直接使用+
来连接字符串的情况,用下面一个简单的例子来说明,进行两个字符串连接操作,即s3 = s1 + s2
。
public class TestString {
public static void main(String[] args) {
String s1 = "www";
String s2 = "ccc";
String s3 = s1 + s2;
}
}
接着javap -c TestString.class
看一下编译后的情况,可以看到编译器其实是对+
进行了转换的,转成了 StringBuilder 对象来操作了,首先使用 s1 创建 StringBuilder 对象,然后用 append
方法连接 s2,最后调用toString
方法完成。
public class com.seaboat.string.TestString {
public com.seaboat.string.TestString();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String www
2: astore_1
3: ldc #18 // String ccc
5: astore_2
6: new #20 // class java/lang/StringBuilder
9: dup
10: aload_1
11: invokestatic #22 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
14: invokespecial #28 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
17: aload_2
18: invokevirtual #31 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #35 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
}
“+”与”append”等价吗
前面可以看到+
在编译器作用下都会转成 StringBuilder 的append
方法执行,所以如果抛开运行效率来说,它们其实本质是一样的。
本质一样是否就能说明它们时等价的呢?或者说能否为了方便直接用+
来连接字符串,剩下的事就交给编译器了?继续看个例子,在这个例子中有个 for 循环进行字符串连接操作。
public class TestString2 {
public static void main(String[] args) {
String s = "www";
for (int i = 0; i < 10; i++)
s += i;
}
}
编译后的情况如下,不熟悉指令没关系,我们只看重要的部分,if_icmplt 8
,这个就是 for 循环的条件判断,小于10则不断跳到8的位置,8后面其实就是创建 StringBuilder 对象,并以本地变量s的值初始化该对象,接着再将本地变量i append
到 StringBuilder 对象中,最后调用toString
方法将所得值存到本地变量s。
这样来看循环中每次都要创建 StringBuilder 对象,而且要调用toString
方法,这样的执行效率显然比较低,而且增加了 GC 的压力。
public class com.seaboat.string.TestString2 {
public com.seaboat.string.TestString2();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16 // String www
2: astore_1
3: iconst_0
4: istore_2
5: goto 30
8: new #18 // class java/lang/StringBuilder
11: dup
12: aload_1
13: invokestatic #20 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
16: invokespecial #26 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
19: iload_2
20: invokevirtual #29 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
23: invokevirtual #33 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: astore_1
27: iinc 2, 1
30: iload_2
31: bipush 10
33: if_icmplt 8
36: return
}
友好写法
把事情都丢给编译器是不友好的,为了能让程序执行更加高效,最好是我们自己来控制 StringBuilder 的实例,比如下面,只创建一个 StringBuilder 实例,后面用append
方法连接字符串。
public class TestString3 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("www");
for (int i = 0; i < 10; i++)
sb.append(i);
}
}
编译后的情况如下,首先创建一个 StringBuilder 对象,使用字符串”www”来实例化该对象,接着循环调用append
方法将本地变量i添加到 StringBuilder 对象中。
public class com.seaboat.string.TestString3 {
public com.seaboat.string.TestString3();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #16 // class java/lang/StringBuilder
3: dup
4: ldc #18 // String www
6: invokespecial #20 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
9: astore_1
10: iconst_0
11: istore_2
12: goto 24
15: aload_1
16: iload_2
17: invokevirtual #23 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: pop
21: iinc 2, 1
24: iload_2
25: bipush 10
27: if_icmplt 15
30: return
}
————-推荐阅读————
跟我交流,向我提问:
公众号的菜单已分为“读书总结”、“分布式”、“机器学习”、“深度学习”、“NLP”、“Java深度”、“Java并发核心”、“JDK源码”、“Tomcat内核”等,可能有一款适合你的胃口。
欢迎关注:
今天的文章字符串连接你用+还是用StringBuilder分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/17913.html