黑马程序员技术交流社区

标题: String和StringBuffer的理解 [打印本页]

作者: 宋浩    时间: 2012-6-13 13:35
标题: String和StringBuffer的理解
本帖最后由 宋浩 于 2012-6-13 13:36 编辑

String对象内容是不可改变的,StringBuffer是可以改变的,并且高效。
首先,请看下面的代码
   StringString str = "hello";
   str=str+"world";
上面两句,虽然str的值最终改变了,但是实际上在编译的时候,第一句str是一个对象,被分配了一个地址,第二句执行时,原来的str被释放,然后重新分配。
str原本指向一 String object instance ("hello"), a + "world" 会造出另一新的 String object instance ("helloworld"), 然后
str再指向这新的 String instance。
StringBufferStringBuffer str2 = new StringBuffer("hello");
str2.append("world");
在这个过程中,只存在str2这么一个对象,str2一直都指向一个 StringBuffer instance。str2.append 也只是改变此 instance 的内容而已。

在我以前的了解中,String是一个final Class, StringBuffer不是。所以对于
String a = "abc"; String b = "def"; String c = a + b ;
  存在一个对象拷贝构造和解析的消耗问题;对于一个StringBuffer来说,
  StringBuffer sb = new StringBuffer();
  sb.append("abc") ;
  sb.append("def");
   因为StringBuffer是一个可以实例化的类,而且它的内建机制
  是维护了一个capacity大小的字符数组,所以它的append操作不存在对象的消耗问题,所以我
得如果存在String连接这种事情,StringBuffer来做会好很多。但事情并不是这么简单,看下面代码
String string1 = "abc" + "def" + "ghi" + "jkl";
StringBuffer sb = new StringBuffer();
sb.append("abc") ;
sb.append("def");
sb.append("ghi") ;
sb.append("jkl");   
String string2 = sb.toString();

如前面所说,Sting的"+"运算肯定比StringBuffer的append()效率低,但经过测试不是这样,为什么?
这里,我们需要理解程序过程的两个时期,一个是编译时,一个是运行时,在编译时,
编译器会对你的程序做出优化,所以String会被优化成"abcdefghijkl",而的StringBuffer只会在运行时才处理。
所以效率是不一样的。

如果代码是这样的:
String str1;
for(int i = 0; i< 100000;i++){
    str1+= String.valueOf(i) ;
}
StringBuffer sb = new StringBuffer();
for(int i = 0; i< 100000;i++){
    sb.append(i) ;
}
String str2 = sb.toString();

如果是这种情况的话,String的效率就大大不如StringBuffer,区别在哪里?就在于运行时和编译时的优化问题上了!

作者: 庄星睿    时间: 2012-6-13 14:11
不错,学习了,测试了一下运行时间,运行确实String不如StringBuffer快
  1. abstract class GetTime
  2. {
  3.         public final void getTime()
  4.         {
  5.                 long t1=System.currentTimeMillis();
  6.                 runCode();
  7.                 long t2=System.currentTimeMillis();
  8.                 System.out.println("运行时间:"+(t2-t1));
  9.         }
  10.         public abstract void runCode();
  11. }
复制代码

作者: 孙浩迪    时间: 2012-6-13 15:10
abstract class GetTime
{
        public final void getTime()
        {
                long t1=System.currentTimeMillis();
                runCode();
                long t2=System.currentTimeMillis();
                System.out.println("运行时间:"+(t2-t1));
        }
        public abstract void runCode();
}


嗯  学习了,
作者: sbeeqnui1987    时间: 2012-6-13 15:47
STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法
使用 StringBuffer 主要就是在性能上的考虑。 String 是一种非常常用的数据类型,但由于 String 是不可变对象,在进行 String 的相关操作的时候会产生许多临时的 String 对象。而 StringBuffer 在操作上是在一个缓冲中进行的,性能当然优越得多。不过,一般做为简单的字符串传递和其它操作,只要不改变字符串内容的操作,用 String 效率会高一些。stringBuffer 比string有一个append()方法..可以在原有的基础上+数据..
作者: sbeeqnui1987    时间: 2012-6-13 15:48
STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法
使用 StringBuffer 主要就是在性能上的考虑。 String 是一种非常常用的数据类型,但由于 String 是不可变对象,在进行 String 的相关操作的时候会产生许多临时的 String 对象。而 StringBuffer 在操作上是在一个缓冲中进行的,性能当然优越得多。不过,一般做为简单的字符串传递和其它操作,只要不改变字符串内容的操作,用 String 效率会高一些。stringBuffer 比string有一个append()方法..可以在原有的基础上+数据..




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2