您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > stringbuffer和string的区别
stringbuffer和string的区别1基本介绍在java中有3个类来负责字符的操作:1.Character是进行单个字符操作的。2.String对一串字符进行操作,不可变类。3.StringBuffer也是对一串字符进行操作,但是可变类。1.1String是对象不是原始类型。为不可变对象,一旦被创建,就不能修改它的值。对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。String是final类,即不能被继承。1.2StringBuffer是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象它只能通过构造函数来建立。StringBuffersb=newStringBuffer();//不能通过赋值符号对他进行赋值。sb=welcometohere!;//error这种写法是错误的对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中赋值的时候可以通过它的append方法.sb.append(hello);字符串连接操作中StringBuffer的效率要比String高:Stringstr=newString(welcometo);str+=here;的处理步骤实际上是通过建立一个StringBuffer,然后调用append(),最后再将StringBuffertoSting();这样的话String的连接操作就比StringBuffer多出了一些附加操作,当然效率上要打折扣。并且由于String对象是不可变对象,每次操作Sting都会重新建立新的对象来保存新的值。这样原来的对象就没用了,就要被垃圾回收.这也是要影响性能的.2String和StringBuffer的区别他们的区别是很大的,它们是两个独立的类,可以这么说吧,除了名字有些相似,完全不相干.String类是不可改变的,如果你更改了String类的实例,那么以前的就“不存在了”,所指向的是一个新的实例。而StringBuffer类是可以更改的。看如下例子,体会这一点:Strings1=Hello;Strings2=Hello;if(s1==s2)System.out.println(Equal);elseSystem.out.println(Notequla);这个程序片断将输出Equal,原因是String类的实例是不能更改的.在生成第2个实例时它发现在缓冲池中已经有了Hello字符串,于是它就直接索引到这个字符串.然而如果,你将第二行代码改为:Strings2=newString(Hello);再运行结果将是Notequal,因为更换了一个构造器形式,在生成第二个实例时,它就不在缓冲池中索引了,而是直接在内存中构造这样一个对象.因此,其句柄的值是不同的.也就是说,当你更改了String类的实例,那么其句柄索引的将是在HeapMemory的另外一个位置的对象,以前的就不能再索引到了.但是,StringBuffer类却不是如此,如果你更改了它的实例,但是在HeapMemory的缓冲池中,索引的是同一个实例.即更改了实例,但句柄的只是不变的,它是可以更改的!string的“+”操作就是根据StringBuilder(或StringBuffer)类及其append方法实现的。String不可变其实就是说一个String对象创建之后不能再在这个对象上做其他操作(如追加,删除一个字符),只能通过创建别的String对象来获取这个效果,而StringBuilder就可以在一个StringBuilder对象上进行改变:Stringstr=“hello”;str=str+“,world!”;//这时并不是在原来的“hello”对象上追加“,world!”,而是重新创建了一个“hello,world!”对象String不能被修改,事实上很简单。就是因为String没有提供写操作方法,没有提供能够修改String对象的成员变量的方法。而StringBuilder则提供了这样的方法(append()等方法)。也许有人会说String不是有个concat方法可以在字符串后面追加字符串吗?呵呵,我们看过API的解释就知道是怎么回事了:publicStringconcat(Stringstr)将指定字符串联到此字符串的结尾。如果参数字符串的长度为0,则返回此String对象。否则,创建一个新的String对象,用来表示由此String对象表示的字符序列和由参数字符串表示的字符序列串联而成的字符序列。对了,区别就在于String的调用concat方法会新建立一个String对象,而StringBuilder的append方法返回的还是原来对象的应用。String对象是不可改变的。每次使用System.String类中的方法之一或进行运算时(如赋值、拼接等)时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。而StringBuilder则不会。在需要对字符串执行重复修改的情况下,与创建新的String对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder类。例如,当在一个循环中将许多字符串连接在一起时,使用StringBuilder类可以提升性能。1.它是引用类型,在堆上分配内存2.运算时会产生一个新的实例3.String对象一旦生成不可改变(Immutable)4.定义相等运算符(==和!=)是为了比较String对象的值(而不是引用)3String和StringBuffer的性能区别3.1创建字符串的较佳途径你可以按照以下方式创建字符串对象:这段代码的输出:JVM是怎样处理字符串的呢?Java虚拟机会维护一个内部的滞留字符串对象的列表(唯一字符串的池)来避免在堆内存中产生重复的String对象。当JVM从class文件里加载字符串字面量并执行的时候,它会先检查一下当前的字符串是否已经存在于滞留字符串列表,如果已经存在,那就不会再创建一个新的String对象而是将引用指向已经存在的String对象,JVM会在内部为字符串字面量作这种检查,但并不会为通过new关键字创建的String对象作这种检查。当然你可以明确地使用String.intern()方法强制JVM为通过new关键字创建的String对象作这样的检查。这样可以强制JVM检查内部列表而使用已有的String对象。所以结论是,JVM会内在地为字符串字面量维护一些唯一的String对象,程序员不需要为字符串字面量而发愁,但是可能会被一些通过new关键字创建的String对象而困扰,不过他们可以使用intern()方法来避免在堆内存上创建重复的String对象来改善Java的运行性能。下一小节会向大家展示更多的信息。下图展示了未使用intern()方法来创建字符串的情况。string_creating_without_intern()method你可以自己使用==操作符和String.equals()方法来编码测试上面提到的区别。==操作符会返回true如果一些引用指向一个相同的对象但不会判断String对象的内容是否相同;String.equals()方法会返回true如果被操作的String对象的内容相同。对于上面的代码会有s1==s2,因为s1和s2两个引用指向同一个对象,对于上面的代码,s3.equals(s4)会返回true因为两个对象的内容都一样为”hello”。你可以从上图看出这种机制。在这里有三个独立的包含了相同的内容(”hello”)的对象,实际上我们不需要这么三个独立的对象——因为要运行它们的话既浪费时间又浪费内存。那么怎样才能确保String对象不会重复呢?下一个话题会涵盖对于内建String机制的兴趣。3.2滞留字符串的优化作用同一个字符串对象被重复地创建是不必要的,String.intern()方法可以避免这种情况。下图说明了String.intern()方法是如何工作的,String.intern()方法检查字符串对象的存在性,如果需要的字符串对象已经存在,那么它会将引用指向已经存在的字符串对象而不是重新创建一个。下图描绘了使用了intern()方法的字符串字面量和字符串对象的创建情况。string_creating_with_intern()method下面的例程帮助大家了解String.intern()方法的重要性。这是上面那段代码的输出结果:待验证,我测试的结果跟这个不同TimetakenforcreationofStringliterals:0millisecondsTimetakenforcreationofStringobjectswith'new'keyword:160millisecondsTimetakenforcreationofStringobjectswithintern():60milliseconds3.3连接字符串时候的优化技巧你可以使用+操作符或者String.concat()或者StringBuffer.append()等办法来连接多个字符串,那一种办法具有最佳的性能呢?如何作出选择取决于两种情景,第一种情景是需要连接的字符串是在编译期决定的还是在运行期决定的,第二种情景是你使用的是StringBuffer还是String。通常程序员会认为StringBuffer.append()方法会优于+操作符或String.concat()方法,但是在一些特定的情况下这个假想是不成立的。1)第一种情景:编译期决定相对于运行期决定请看下面的StringTest3.java代码和输出结果。这是上面的代码的输出结果:很有趣地,+操作符居然比StringBuffer.append()方法要快,为什么呢?这里编译器的优化起了关键作用,编译器像下面举例的那样简单地在编译期连接多个字符串。它使用编译期决定取代运行期决定,在你使用new关键字来创建String对象的时候也是如此。编译前:Stringresult=Thisis+testingthe+difference+between+String+and+StringBuffer;编译后:Stringresult=ThisistestingthedifferencebetweenStringandStringBuffer;这里String对象在编译期就决定了而StringBuffer对象是在运行期决定的。运行期决定需要额外的开销当字符串的值无法预先知道的时候,编译期决定作用于字符串的值可以预先知道的时候,下面是一个例子。编译前:publicStringgetString(Stringstr1,Stringstr2){returnstr1+str2;}编译后:returnnewStringBuffer().append(str1).append(str2).toString();运行期决定需要更多的时间来运行。2)第二种情景:使用StringBuffer取代String看看下面的代码你会发现与情景一相反的结果——连接多个字符串的时候StringBuffer要比String快。这是上面的代码的输出结果:看得出StringBuffer.append()方法要比+操作符要快得多,为什么呢?原因是两者都是在运行期决定字符串对象,但是+操作符使用不同于StringBuffer.append()的规则通过String和StringBuffer来完成字符串连接操作。(译注:什么样的规则呢?)3.4借助StringBuffer的初始化过程的优化技巧你可以通过StringBuffer的构造函数来设定它的初始化容量,这样可以明显地提升性能。这里提到的构造函数是StringBuffer(intlength),length参数表示当前的StringBuffer能保持的字符数量。你也可以使用ensureCapacity(intminimumcapacity)方法在StringB
本文标题:stringbuffer和string的区别
链接地址:https://www.777doc.com/doc-2850759 .html