深度剖析StringBuilder can be replaced with String
2020/2/16 8:24:29
本文主要是介绍深度剖析StringBuilder can be replaced with String,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、背景
在写代码的时候使用 StringBuilder 进行字符串拼接时,IDEA 很可能会给出下面的提示: ‘StringBuilder’ can be replaced with ‘String’ 。
那么为什么会给出这种提示?这种提示意味着什么?
二、思考
之前有讲过:“每一个疑问背后都隐藏着至少一个盲点和学习的绝佳机会”。因此我们不会轻易放过这个机会。
另外很多人这个时候可能就要开始百度了!
停!!
“《阿里巴巴Java开发手册》详解” 专栏里有讲到“先猜想后验证”的思想,对学习源码等有很大帮助,这样印象会更深刻。
根据提示:‘StringBuilder’ can be replaced with ‘String’ ,说明这种情况下可以将 StringBuilder
替换成 String
。
我们知道之所以用 StringBuilder
是为了避免字符串拼接过程中产生很多不必要的字符串对象。
那么既然可以替换为 String
,说明这种情况下两者可能等价,也就是说底层是一样的。
三、分析
“《阿里巴巴Java开发手册》详解” 专栏里有讲过写 DEMO ,反编译和反汇编是学习的一个重要手段。
那咱们直接写个 DEMO验证下吧:
public class StringDemo { public static void main(String[] args) { String a = "a"; Integer b = 0; Long c = 1000L; useStringBuilder(a, b, c); usePlus(a, b, c); } /** * 使用 StringBuilder 拼接 */ private static void useStringBuilder(String a, Integer b, Long c) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(a).append(b).append(c); System.out.println(stringBuilder.toString()); } /** * 直接使用+号进行字符串拼接 */ private static void usePlus(String a, Integer b, Long c) { System.out.println(a + b + c); } }
使用 IDEA 自带的反编译工具,发现和源代码几乎相同(这里就不给出了)。
接下来尝试反汇编 javap -c -p StringDemo
(之前已经通过 javac 进行了编译):
public class com.chujianyun.common.str.StringDemo { public com.chujianyun.common.str.StringDemo(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc #2 // String a 2: astore_1 3: iconst_0 4: invokestatic #3 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 7: astore_2 8: ldc2_w #4 // long 1000l 11: invokestatic #6 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 14: astore_3 15: aload_1 16: aload_2 17: aload_3 18: invokestatic #7 // Method useStringBuilder:(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Long;)V 21: aload_1 22: aload_2 23: aload_3 24: invokestatic #8 // Method usePlus:(Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Long;)V 27: return private static void useStringBuilder(java.lang.String, java.lang.Integer, java.lang.Long); Code: 0: new #9 // class java/lang/StringBuilder 3: dup 4: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V 7: astore_3 8: aload_3 9: aload_0 10: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 13: aload_1 14: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 21: pop 22: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream; 25: aload_3 26: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 29: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 32: return private static void usePlus(java.lang.String, java.lang.Integer, java.lang.Long); Code: 0: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #9 // class java/lang/StringBuilder 6: dup 7: invokespecial #10 // Method java/lang/StringBuilder."<init>":()V 10: aload_0 11: invokevirtual #11 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 14: aload_1 15: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 18: aload_2 19: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 22: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: invokevirtual #15 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 28: return }
注:大家也可以使用专栏第一个加餐文章中推荐的 jclasslib 字节码插件插件来查看字节码
大家可以对比下 usePlus
函数和 useStringBuilder
函数的字节码指令会发现带变量的 + 号拼接方式最终将转化为 StringBuilder 进行字符串拼接。
相当于是编译器的优化,因此 IDEA 检测到两者等价,为了让代码更加简洁,所以给出了上述提示。
为了再次印证这个想法我们打开《Java 语言规范》15.18.1. String Concatenation Operator +:
An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate
String
object. To increase the performance of repeated string concatenation, a Java compiler may use theStringBuffer
class or a similar technique to reduce the number of intermediateString
objects that are created by evaluation of an expression.Java 语言实现可以选择在某个步骤中执行转换和拼接,以避免先创建然后又丢弃中间的字符串对象。为了提高字符串连接操作的性能,Java 编译器可以使用功能 StringBuilder 类或者类似的技术来减少计算表达式时创建的中间 String 对象的数量。
因此问题就彻底清楚了。
四、总结
之前有写过《为什么要推荐大家学习字节码》和《每一个疑问背后都隐藏着至少一个盲点和学习的绝佳机会》两篇文章。希望大家能够真正理解学习字节码的用处;能够真真抓住每一次疑问,通过对每一个疑问的深入探究来彻底掌握某个知识。另外强烈推荐大家多看《Java 语言规范》和《Java 虚拟规范》,它们更全面且更权威。
希望本文能对大家有帮助。欢迎关注我的专栏,如果有任何问题想和我交流,欢迎留言评论。
这篇关于深度剖析StringBuilder can be replaced with String的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-30uniAPP 实现全屏左右滚动滚动的效果-icode9专业技术文章分享
- 2024-06-30如何在本地使用授权或插件-icode9专业技术文章分享
- 2024-06-30伪静态规则配置方法汇总-icode9专业技术文章分享
- 2024-06-29易优CMS安装常见问题汇总-icode9专业技术文章分享
- 2024-06-28易优新手必读安装教程-icode9专业技术文章分享
- 2024-06-28忘记eyoucms后台密码怎么办?-icode9专业技术文章分享
- 2024-06-26终极指南:Scrum中如何设置需求优先级
- 2024-06-26AI大模型企业应用实战(25)-为Langchain Agent添加记忆功能
- 2024-06-26小白家庭 nas 搭建方案-icode9专业技术文章分享
- 2024-06-23AI大模型企业应用实战(14)-langchain的Embedding