不好意思各位,又震惊了。 今天写代码的时候在AndroidStudio遇到黄色提示,打开看了一下,惊了。
先上代码吧:
展开提示内容看一看:
'StringBuilder sb' can be replaced with 'String' less... (Ctrl+F1) Reports any usages of java.lang.StringBuffer and java.lang.StringBuilder which can be replaced with a single java.lang.String concatenation. Using a String concatenation makes the code shorter and simpler. This inspection only reports when the resulting concatenation is at least as efficient or more efficient than the original StringBuffer or StringBuilder code.
提示说代码这里的StringBuilder或StringBuffer可以使用单String的连加“+”来替换。 使用String连加可以使代码更简洁。这个代码检查提示只有当使用String连加的效率不低于StringBuilder或StringBuffer的时候才会报告。
咋回事小老弟,StringBuilder明显效率更高不是吗? 来一起回忆一下
StringBuilder、StringBuffer和String的区别吧。
不可变角度区别
- String是不可变的,如果你尝试修改他的值,便会创建一个新的String对象
- 而StringBuffer和StringBuilder是可变的,可以修改他们的值。
线程安全角度的区别
- StringBuffer是线程安全的,而当你只需要在单线程中使用字符串的话,使用StringBuilder是更好的选择,因为StringBuilder有比StringBuffer更好的效率。 当然String是不可变的,也是线程安全的。
- 如果你不会对字符串做修改,当然应该使用String对象
- 如果你的字符串会做修改,比如会有一些复杂逻辑对字符串进行处理,单仅会在单线程使用,使用StringBuilder已经足够优秀。
- 如果你的字符串会做修改,并且会有多线程对其做操作,那么你应该使用StringBuffer,因为StringBuffer是线程安全的。
这么一回忆,是不是懵了,尝试修改String的时候会创建新的String对象,而StringBuilder是可变对象,效率明显更高啊。
难道性能一样吗?
经过一番研究,终于找到了原因。 首先我们按IDE提示,将代码改为连加形式:
public static void main(String args[]) {
String s = "AAA";
String ss = "BBB" + s + "CCC" + 10;
System.out.println(ss);
}
然后用javap命令反编译class文件,javap -verbose StringBuilderTest
查看字节码bytecode:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: ldc #2 // String AAA
2: astore_1
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: ldc #5 // String BBB
12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
15: aload_1
16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: ldc #7 // String CCC
21: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: bipush 10
26: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
29: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
32: astore_2
33: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
36: aload_2
37: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: return
清楚的看到12、16、21、26行 编译器自动为我们优化,使用了StringBuilder的append连接字符串。
到这里我们明白了,虽然在源程序中使用了”+”,但在编译时编译器仍然将”+”转换成StringBuilder,在效率上和直接代码里用StringBuilder的append是一样的。 Studio为我们做提示是考虑到代码的简洁性。
在循环中使用连加
如果连接字符串行表达式很简单(如上面的顺序结构),那么”+”和StringBuilder基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的Java Byte Code就会有很大的区别。 现在给我们的代码加上一个for循环看看:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
0: ldc #2 // String AAA
2: astore_1
3: ldc #3 // String
5: astore_2
6: iconst_0
7: istore_3
8: iload_3 **这里开始循环**
9: bipush 10
11: if_icmpge 54
14: new #4 // class java/lang/StringBuilder
17: dup
18: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
21: aload_2
22: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: ldc #7 // String BBB
27: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: ldc #8 // String CCC
36: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: bipush 10
41: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
44: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
47: astore_2
48: iinc 3, 1
51: goto 8 **跳转到第8行做循环**
54: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
57: aload_2
58: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
61: return
从字节码我们可以看出,new StringBuilder是在循环内部进行的。 所以每次循环,都会创建一个StringBuilder,这与直接在代码中使用单一StringBuilder的append效率肯定要低很多了。
所以Studio会像我们意料的那样进行提示。
总结一下: 如果只是简单逻辑顺序连接字符串,可以使用String的“+”,因为编译器会为我们自动优化为StringBuilder,而Studio进行提示考虑的是,既然性能一样,那么就要考虑代码的可读性,使用连加+,代码更简洁,更容易理解;而如果在循环中进行字符串拼接,那么一定要使用StringBuilder类型,这样性能会优秀很多。
今天的文章震惊!AndroidStudio竟提示用String连加替代StringBuilder?分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/23561.html