Java中何时用String,何时用StringBuilder
来源:互联网 发布:重庆seo博客sina 编辑:程序博客网 时间:2024/05/22 14:22
大家都知道,String对象是不可变的,不可变性会带来效率问题。为String对象重载“+”操作符时,都会自动生成一个新的String对象。
也有人说,String在上述的问题中已经会自动引入StringBuilder来解决效率问题。
为此,我在《Java编程思想》中找到了答案。
javac TestString.java
用javap来反编译上述代码,看看都发生了什么故事:
javap -c TestString
结果如下:
从上述代码中看,编译器确实创建了一个StringBuilder对象。
但是,这并不能因此就说明可以随意的使用String对象。下面又举了个例子:
反编译一下:
[linc@localhost TestString]$ javac StringAndBuilder.java
[linc@localhost TestString]$ javap -c StringAndBuilder
注意到implicit方法,从第8行到第35行构成了一个循环体。StringBuilder是在循环体内构造的,也就是说,每经过一次循环,就会创建一个新的StrinBuilder对象。
再看explicit方法,循环部分的代码更简短、简单,而且只生成了一个StrinBuilder对象。
结论:
当为一个类编写toString()方法时,如果操作比较简单,就可以信赖编译器,它会为你合理的构造最终的字符串结果。如果使用了循环,那么最好自己创建一个StringBuilder对象。
如果拿不准该用那种方式,就用javap来分析你的程序吧!
另外,linc之前还翻译了一段小文章,是讲String、StringBuffer和StringBuilder之间的区别的:http://blog.csdn.net/lincyang/article/details/6333041
也有人说,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
- Java中何时用String,何时用StringBuilder
- 何时使用 String, StringBuffer, StringBuilder
- 在Objective-C中何时用self.何时不用?
- 在Objective-C中何时用self.何时不用?
- 在Objective-C中何时用self.何时不用?
- 何时用指针,何时用引用?
- 何时用继承?何时用组合
- 何时用rest,何时用soap
- 何时用类?何时用接口?
- 何时用抽象类,何时用接口?
- 何时用Delegate和何时用Block?
- Java中hashcode何时使用?
- 何时用内联函数?
- 转载 何时用接口
- 何时该用volatile?
- 何时用自定义标签?
- 何时用new?
- 何时
- [Redhat学习笔记]:软RAID创建的方式以及分析。(手把手教你做RAID)
- 学习LR中的手动关联
- c 语言 ","号运算符的用法
- 我也有博客啦
- JDK+MyEclipse+Tomcat的配置
- Java中何时用String,何时用StringBuilder
- iOS开发之缓存(一):内存缓存
- [Repaste] Windows 8 for software developers: the Longhorn dream reborn?
- C# 使用Using和Try/Finally 进行资源清理
- Tips on how to decide on a great luxurious enjoy
- 2011-7-30 17:10:35
- MyEclipse的破解代码
- DDK与WDK
- 正则表达式30分钟入门教程