关于java中字符串联接使用 Stirng+String+. 效率的一点想法
关于java中字符串连接使用 Stirng+String+... 效率的一点想法
记得自己还是个连菜鸟都算不上的coder的时候,老鸟们总教育我:代码里不要出现String+String+...这种代码,非多线程的情况下要用StringBuilder效率才高
当时没啥感觉,最近闲来无事,想看看java编译器都对String+String+...这种代码怎么处理的呢?于是发现javac也是用StringBuilder来处理的,所以我感觉这两者效率上是没有区别的,如本人理解有错,望老鸟给予指正...
请看代码吧,主要代码我都加上了注释
以上代码编译成class文件后
用javap Test -verbose 命令看下字节码文件中的内容:
注意下面代码第100行,重点所在
记得自己还是个连菜鸟都算不上的coder的时候,老鸟们总教育我:代码里不要出现String+String+...这种代码,非多线程的情况下要用StringBuilder效率才高
当时没啥感觉,最近闲来无事,想看看java编译器都对String+String+...这种代码怎么处理的呢?于是发现javac也是用StringBuilder来处理的,所以我感觉这两者效率上是没有区别的,如本人理解有错,望老鸟给予指正...
请看代码吧,主要代码我都加上了注释
package test; public class Test { public static void main(String[] args) { String s1 = new String("小菜鸟"); String s2 = new String("大菜鸟"); String resultString = s1 + s2 + "老鸟"; } }
以上代码编译成class文件后
用javap Test -verbose 命令看下字节码文件中的内容:
注意下面代码第100行,重点所在
D:\Workspace\MyEclipse\workspace\Test\bin\test>javap Test -verbose Compiled from "Test.java" public class test.Test extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 50 Constant pool: const #1 = class #2; // test/Test const #2 = Asciz test/Test; const #3 = class #4; // java/lang/Object const #4 = Asciz java/lang/Object; const #5 = Asciz <init>; const #6 = Asciz ()V; const #7 = Asciz Code; const #8 = Method #3.#9; // java/lang/Object."<init>":()V const #9 = NameAndType #5:#6;// "<init>":()V const #10 = Asciz LineNumberTable; const #11 = Asciz LocalVariableTable; const #12 = Asciz this; const #13 = Asciz Ltest/Test;; const #14 = Asciz main; const #15 = Asciz ([Ljava/lang/String;)V; const #16 = class #17; // java/lang/String const #17 = Asciz java/lang/String; const #18 = String #19; // 小菜鸟 const #19 = Asciz 小菜鸟; const #20 = Method #16.#21; // java/lang/String."<init>":(Ljava/lan g/String;)V const #21 = NameAndType #5:#22;// "<init>":(Ljava/lang/String;)V const #22 = Asciz (Ljava/lang/String;)V; const #23 = String #24; // 大菜鸟 const #24 = Asciz 大菜鸟; const #25 = class #26; // java/lang/StringBuilder const #26 = Asciz java/lang/StringBuilder; const #27 = Method #16.#28; // java/lang/String.valueOf:(Ljava/lang /Object;)Ljava/lang/String; const #28 = NameAndType #29:#30;// valueOf:(Ljava/lang/Object;)Ljava/lang/Strin g; const #29 = Asciz valueOf; const #30 = Asciz (Ljava/lang/Object;)Ljava/lang/String;; const #31 = Method #25.#21; // java/lang/StringBuilder."<init>":(Lj ava/lang/String;)V const #32 = Method #25.#33; // java/lang/StringBuilder.append:(Ljav a/lang/String;)Ljava/lang/StringBuilder; const #33 = NameAndType #34:#35;// append:(Ljava/lang/String;)Ljava/lang/String Builder; const #34 = Asciz append; const #35 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuilder;; const #36 = String #37; // 老鸟 const #37 = Asciz 老鸟; const #38 = Method #25.#39; // java/lang/StringBuilder.toString:()L java/lang/String; const #39 = NameAndType #40:#41;// toString:()Ljava/lang/String; const #40 = Asciz toString; const #41 = Asciz ()Ljava/lang/String;; const #42 = Asciz args; const #43 = Asciz [Ljava/lang/String;; const #44 = Asciz s1; const #45 = Asciz Ljava/lang/String;; const #46 = Asciz s2; const #47 = Asciz resultString; const #48 = Asciz SourceFile; const #49 = Asciz Test.java; { public test.Test(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #8; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Ltest/Test; public static void main(java.lang.String[]); Code: Stack=3, Locals=4, Args_size=1 0: new #16; //class java/lang/String |我加上的:创建一个新对象,对象类型存储在常量池#16 3: dup //我加上的:复制栈顶部一个字长的内容 4: ldc #18; //String 小菜鸟 |我加上的:把常量池中索引为#18的值压入栈 6: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V |我加上的:调用初始化方法 9: astore_1 //我加上的:将引用类型存入局部变量1 10: new #16; //class java/lang/String |我加上的:10-19同上实例化另一个String对象(大菜鸟) 13: dup 14: ldc #23; //String 大菜鸟 16: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V 19: astore_2 20: new #25; //class java/lang/StringBuilder |我加上的:创建一个StringBuilder对象 23: dup 24: aload_1 //我加上的:从局部变量1中装载引用类型 25: invokestatic #27; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 28: invokespecial #31; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 31: aload_2 //我加上的:从局部变量2中装载引用类型 //哈哈,看到这里了吧,javac(我的jdk版本是1.6)编译后的字节码对于String+String+...的处理也是使用StringBuilder的append的 32: invokevirtual #32; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 35: ldc #36; //String 老鸟 //同理,连接字符串“老鸟” 37: invokevirtual #32; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 40: invokevirtual #38; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 43: astore_3 44: return LineNumberTable: line 7: 0 line 8: 10 line 10: 20 line 11: 44 LocalVariableTable: Start Length Slot Name Signature 0 45 0 args [Ljava/lang/String; 10 35 1 s1 Ljava/lang/String; 20 25 2 s2 Ljava/lang/String; 44 1 3 resultString Ljava/lang/String; } D:\Workspace\MyEclipse\workspace\Test\bin\test>