String和StringBuffer的区别详谈[转帖]

  看到这篇文章对String和StringBuffer的区别说的和详细,与大家分享一下:
 
String类用来表示那些创建后就不会再改变的字符串,它是immutable的。而StringBuffer类用来表示内容可变的字符串,并提供了修改底层字符串的方法。
      当我们进行字符拼接时,请使用StringBuffer类而非String类,因为前者将比后者快上百倍。
的确,在程序的太多场合我们都会进行字符串拼接工作,简单的代码示例如下:
String str="You are nice.";
str+="I love you so much.";
如果用StringBuffer类的话,代码如下:
StringBuffer str= new StringBuffer("You are nice.");
str.append("I love you so much.");
        从表面看来String类只用一个加号(+)便完成了字符串的拼接,而StringBuffer类却要调用一个append()方法,是否实现起来更简洁,更单纯呢?其实不然,让我们了解一下程序运行内部发生了哪些事情:
        经编译后程序的bytecode(字节码)展示出了实质:  在用String类对象直接拼接时,JVM会创建一个临时的StringBuffer类对象,并调用其append()方法完成字符串的拼接,这是因为 String类是不可变的,拼接操作不得不使用StringBuffer类(并且--JVM会将"You are nice."和"I love you so much."创建为两个新的String对象)。之后,再将这个临时StringBuffer对象转型为一个String,代价不菲!可见,在这一个简单的一次拼接过程中,我们让程序创建了四个对象:两个待拼接的String,一个临时StringBuffer,和最后将StringBuffer转型成为的String--它当然不是最初的str了,这个引用的名称没变,但它指向了新的String对象。
        而如果直接使用StringBuffer类,程序将只产生两个对象:最初的StringBuffer和拼接时的String("I love you so much."),也不再需要创建临时的StringBuffer类对象而后还得将其转换回String对象。
        可以想象,当我们的字符串要被循环拼接若干段时,用String类直接操作会带来多少额外的系统开销,生成多少无用的临时StringBuffer对象,并处理多少次无谓的强制类型转换哪。
------------------------------
记得以前在网上看到一篇关于java面试题的文章,里面好像有个题就是关于String与StringBuffer的,具体的记不清了,大概内容如下:
请说出下面代码块存在的问题:
String tmp = “”;
for(int i=0;i<n;I++){
    tmp +=”x”;
}
当时网上有人只是简单的说了要改用StringBuffer,这个存在效率问题,而没有进一步说明,其实我也很郁闷,是什么效率问题呢?“顾名思义,StringBuffer之所以效率好,应该是它提供了缓存机制吧”,我想很多朋友是这样想的吧,HOHO。
当昨天晚上读到Effective java一书的时候,我才恍然大悟,原来String是一个支持非可变性的类,这种类的特点是状态固定(不存在任何修改对象的方法),在该对象的生存周期内,它的值是永远不变的(它是线程安全的),它们更容易设计、实现、使用,不易出错,更加安全。
由于String类是支持非可变性的,所以,当执行tmp +=”x”的时候,实际上是另外创建了一个对象,而tmp原来指向的那个对象就成了垃圾(当它没有其它引用的时候),这样的话一个循环就会产生n多对象,可以相象内存的浪费,怕怕。
 
先看一下String类中substring方法的实现
public String substring(int beginIndex, int endIndex) {
       if (beginIndex < 0) {
           throw new StringIndexOutOfBoundsException(beginIndex);
       }
       if (endIndex > count) {
           throw new StringIndexOutOfBoundsException(endIndex);
       }
       if (beginIndex > endIndex) {
           throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
       }
       return ((beginIndex == 0) && (endIndex == count)) ? this :
           new String(offset + beginIndex, endIndex - beginIndex, value);
}
从蓝色部份可以看出,它是重新创建了一个新的对象,符合“支持非可变性”的原则,但这却也显示出了非可变类的真正惟一的缺点,就是“对于每一个不同的值都要求一个单独的对象”。
那为什么String要设计成非可变类呢?我觉得String是java中使用最为频繁的一个类,只有使其支持非可变性,才有可能避免一系列的问题,比如说:
String a,b,c;
a=”test”;
b=a;
c=b;
processA(){
    ……..
}
ProcessB(){
    ……..
}
ProcessC(){
    ……..
}
当String支持非可变性的时候,它们的值很好确定,不管调用哪个方法,都互不影响,如果它不支持的话,那么我无法想象其结果。
StringBuffer做为String的“配套类(companying class)”,它的作用就是为了解决上述问题的,StringBuffer扮演了String的可变配套类角色。非可变类本质上是线程安全的,它们不要求做同步处理,我们可以将其共享给所有用户,让所有的“客户端程序员”都可以直接使用此类而不需要做任何额外的工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值