Java中何时用String,何时用StringBuilder

来源:互联网 发布:重庆seo博客sina 编辑:程序博客网 时间:2024/05/22 14:22
大家都知道,String对象是不可变的,不可变性会带来效率问题。为String对象重载“+”操作符时,都会自动生成一个新的String对象。
也有人说,String在上述的问题中已经会自动引入StringBuilder来解决效率问题。


为此,我在《Java编程思想》中找到了答案。


第一个小例子:

package com.linc.TestString;public class TestString {public static void main(String[] args){String mango = "mango";String someting = "abc" + mango + "def" + 47;System.out.println(someting);}}
执行编译,命令:
javac TestString.java
用javap来反编译上述代码,看看都发生了什么故事:
javap -c TestString


结果如下:

Compiled from "TestString.java"public class com.linc.TestString.TestString extends java.lang.Object{public com.linc.TestString.TestString();  Code:   0:aload_0   1:invokespecial#1; //Method java/lang/Object."<init>":()V   4:returnpublic static void main(java.lang.String[]);  Code:   0:ldc#2; //String mango   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 abc   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 def   21:invokevirtual#6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   24:bipush47   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}

从上述代码中看,编译器确实创建了一个StringBuilder对象。
但是,这并不能因此就说明可以随意的使用String对象。下面又举了个例子:

package com.linc.TestString;public class StringAndBuilder {public String implicit(String[] fields){String result="";for(int i=0;i<fields.length;++i){result+=fields[i];}return result;}public String explicit(String[] fields){StringBuilder result=new StringBuilder();for(int i=0;i<fields.length;++i){result.append(fields[i]);}return result.toString();}}

反编译一下:
[linc@localhost TestString]$ javac StringAndBuilder.java 
[linc@localhost TestString]$ javap -c StringAndBuilder

Compiled from "StringAndBuilder.java"public class com.linc.TestString.StringAndBuilder extends java.lang.Object{public com.linc.TestString.StringAndBuilder();  Code:   0:aload_0   1:invokespecial#1; //Method java/lang/Object."<init>":()V   4:returnpublic java.lang.String implicit(java.lang.String[]);  Code:   0:ldc#2; //String    2:astore_2   3:iconst_0   4:istore_3   5:iload_3   6:aload_1   7:arraylength   8:if_icmpge38   11:new#3; //class java/lang/StringBuilder   14:dup   15:invokespecial#4; //Method java/lang/StringBuilder."<init>":()V   18:aload_2   19:invokevirtual#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   22:aload_1   23:iload_3   24:aaload   25:invokevirtual#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   28:invokevirtual#6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   31:astore_2   32:iinc3, 1   35:goto5   38:aload_2   39:areturnpublic java.lang.String explicit(java.lang.String[]);  Code:   0:new#3; //class java/lang/StringBuilder   3:dup   4:invokespecial#4; //Method java/lang/StringBuilder."<init>":()V   7:astore_2   8:iconst_0   9:istore_3   10:iload_3   11:aload_1   12:arraylength   13:if_icmpge30   16:aload_2   17:aload_1   18:iload_3   19:aaload   20:invokevirtual#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   23:pop   24:iinc3, 1   27:goto10   30:aload_2   31:invokevirtual#6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   34:areturn}

注意到implicit方法,从第8行到第35行构成了一个循环体。StringBuilder是在循环体内构造的,也就是说,每经过一次循环,就会创建一个新的StrinBuilder对象。
再看explicit方法,循环部分的代码更简短、简单,而且只生成了一个StrinBuilder对象。


结论:
当为一个类编写toString()方法时,如果操作比较简单,就可以信赖编译器,它会为你合理的构造最终的字符串结果。如果使用了循环,那么最好自己创建一个StringBuilder对象。
如果拿不准该用那种方式,就用javap来分析你的程序吧!


另外,linc之前还翻译了一段小文章,是讲String、StringBuffer和StringBuilder之间的区别的:http://blog.csdn.net/lincyang/article/details/6333041

原创粉丝点击