读书人

String ,StringBuilder,StringBuffer的

发布时间: 2012-12-26 14:39:28 作者: rapoo

String ,StringBuilder,StringBuffer的区别

String类代表字符串,java程序中所有的字符串字面值(如”abc”)都作为此类来实现,字符串是常量,它们的值在创建后就不能改变。因为字符串不可变,因此可以共享它们。


StringBuffer,线程安全的可变字符序列。一个类似于String的字符缓冲区,但不能修改,是指这个对象本身不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。


StringBuilder, 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。
有时候,我们经常会这样写程序,譬如

?然后我们运行程序,控制台便马上打印出了我们想要的结果。可是,在这个程序片段的内部,它的执行机理以及这样写,性能上是个什么样的情况,我们可能很少去研究,下面我将来谈一谈重载的’+’操作符与StringBuilder的区别。

首先,我们先说String。众所周知,String是java.lang包中的一个类,它在java编程中使用的非常频繁。查看javaAPI可以看到,这个类的声明是public final class String….,正因为是final的,可以想到这个类已经创建,那么它就是不可变的。有了这个认识,我们再说上面的程序,每用’+’操作符对String对象进行一次运算,那么它都会产生一个新的String对象,这个新产生的String对象既包含原来的String对象也包含添加进来的String对象。毫无疑问,上面那段代码必定能很好的工作,只是为了把几个字符串拼接到一起,按照上面的做法会产生大量的”中间”String对象,这些中间对象也是需要被GC回收的。为了看清楚这段代码的执行细节,我们可以用这么一个命令?
Javap? c? Concatenation
控制台给我们列出了这样的信息:

public java.lang.String implicit(java.lang.String[]);  Code:   0:   ldc     #16; //String   2:   astore_2   3:   iconst_0   4:   istore_3   5:   goto    32   8:   new     #18; //class java/lang/StringBuilder   11:  dup   12:  aload_2   13:  invokestatic    #20; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;   16:  invokespecial   #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V   19:  aload_1   20:  iload_3   21:  aaload   22:  invokevirtual   #29; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   25:  invokevirtual   #33; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   28:  astore_2   29:  iinc    3, 1   32:  iload_333:  aload_1   34:  arraylength35:  if_icmplt       8  38:  aload_2   39:  areturnpublic java.lang.String explicit(java.lang.String[]);  Code:   0:   new     #18; //class java/lang/StringBuilder   3:   dup   4:   invokespecial   #45; //Method java/lang/StringBuilder."<init>":()V   7:   astore_2   8:   iconst_0   9:   istore_3   10:  goto    24   13:  aload_2   14:  aload_1   15:  iload_3   16:  aaload   17:  invokevirtual   #29; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   20:  pop   21:  iinc    3, 1   24:  iload_3   25:  aload_1   26:  arraylength   27:  if_icmplt       13   30:  aload_2   31:  invokevirtual   #33; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;  34:  areturn
?

从两分字节码可以看出,第二个的更短小简洁,并且第一个在每个循环中都会创建一个StringBuilder对象,而第二个方法始终只有一个StringBuilder对象。然而这两者的性能差异确实有很大差别的。
所以,当我们的连接操作很简单的时候,可以使用String,但是若涉及到循环,那么最好使用StrignBuilder.

?

读书人网 >编程

热点推荐