String 与 Stringbuffer.docx
《String 与 Stringbuffer.docx》由会员分享,可在线阅读,更多相关《String 与 Stringbuffer.docx(14页珍藏版)》请在冰豆网上搜索。
String与Stringbuffer
String与Stringbuffer.
2007年06月08日星期五11:
33
String的创建
Strings="hello";
JVM先根据内容"hello"查找对象,如果没有找到,则在heap上创建新对象,并将其赋予s1,否则使用已经存在的对象
Strings=newString("hello");
JVM直接在heap上创建新的对象,所以在heap中会出现内容相同,地址不同的String对象
String的比较
"=="比较地址
"equals"比较内容
举例:
Strings1="hello";
Strings2="hello";
Strings3=newString("hello");
s1==s2;//true地址相同
s1==s3;//false地址不同
s1.equals(s2);//true内容相同
s1.equals(s3);//true内容相同
intern()方法
查找内容相同(equals())的字符串
Strings1="hello";//hello不存在,jvm创建新对象
(1)
Strings2=newString("hello");//创举新对象
(2),这时heap中存在两个内容为hello的对象
s1==s2;//false//地址不同
s1.equals(s2);//true//内容相同
s2=s2.intern();//true//找到对象
(1)并赋予s2
s1==s2;//true!
!
//注意:
此时s1,s2同指向
(1)
效率:
String与StringBuffer
情景1:
(1)Stringresult="hello"+"world";
(2)StringBufferresult=newString().append("hello").append("world");
(1)的效率好于
(2),不要奇怪,这是因为JVM会做如下处理
编译前Stringresult="hello"+"world";
编译后Stringresult="helloworld";
情景2:
(1)publicStringgetString(Strings1,Strings2){
returns1+s2;
}
(2)publicStringgetString(Strings1,Strings2){
returnnewStringBuffer().append(s1).append(s2);
}
(1)的效率与
(2)一样,这是因为JVM会做如下处理
编译前returns1+s2;
编译后returnnewStringBuffer().append(s1).append(s2);
情景3:
(1)Strings="s1";
s+="s2";
s+="s3";
(2)StringBuffers=newStringBuffer().append("s1").append("s2").append("s3");
(2)的效率好于
(1),因为String是不可变对象,每次"+="操作都会造成构造新的String对象
情景4:
(1)StringBuffers=newStringBuffer();
for(inti=0;i<50000;i++){
s.append("hello");
}
(2)StringBuffers=newStringBuffer(250000);
for(inti=0;i<50000;i++){
s.append("hello");
}
(2)的效率好于
(1),因为StringBuffer内部实现是char数组,默认初始化长度为16,每当字符串长度大于char
数组长度的时候,JVM会构造更大的新数组,并将原先的数组内容复制到新数组,
(2)避免了复制数组的开销
关键点
1).简单的认为.append()效率好于"+"是错误的!
2).不要使用new创建String
3).注意.intern()的使用
4).在编译期能够确定字符串值的情况下,使用"+"效率最高
5).避免使用"+="来构造字符串
6).在声明StringBuffer对象的时候,指定合适的capacity,不要使用默认值(18)
7).注意以下二者的区别不一样
-Strings="a"+"b";
-Strings="a";
s+="b";
String和StringBuffer之概览
创建字符串的较佳途径
滞留字符串带来的优化
连接字符串时的优化技巧
借助StringBuffer的初始化过程的优化技巧
关键点
String和StringBuffer之概览
非可变对象一旦创建之后就不能再被改变,可变对象则可以在创建之后被改变。
String对象是非可变对象,StringBuffer对象则是可变对象。
为获得更佳的性能你需要根据实际情况小心谨慎地选择到底使用这两者中的某一个。
下面的话题会作详细的阐述。
(注意:
这个章节假设读者已经具备Java的String和StringBuffer的相关基础知识。
)
创建字符串的较佳途径
你可以按照以下方式创建字符串对象:
1.Strings1="hello";
Strings2="hello";
2.Strings3=newString("hello");
Strings4=newString("hello");
上面哪种方式会带来更好的性能呢?
下面的代码片断用来测量二者之间的区别。
StringTest1.java
packagecom.performance.string;
/**Thisclassshowsthetimetakenforcreationof
*StringliteralsandStringobjects.
*/
publicclassStringTest1{
publicstaticvoidmain(String[]args){
//createStringliterals
longstartTime=System.currentTimeMillis();
for(inti=0;i<50000;i++){
Strings1="hello";
Strings2="hello";
}
longendTime=System.currentTimeMillis();
System.out.println("TimetakenforcreationofStringliterals:
"
+(endTime-startTime)+"milliseconds");
//createStringobjectsusing'new'keyword
longstartTime1=System.currentTimeMillis();
for(inti=0;i<50000;i++){
Strings3=newString("hello");
Strings4=newString("hello");
}
longendTime1=System.currentTimeMillis();
System.out.println("TimetakenforcreationofStringobjects:
"
+(endTime1-startTime1)+"milliseconds");
}
}
这段代码的输出:
TimetakenforcreationofStringliterals:
0milliseconds
TimetakenforcreationofStringobjects:
170milliseconds
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.equals()方法来编码测试上面提到的区别。
==操作符会返回true如果一些引用指向一个相同的对象但不会判断String对象的内容是否相同;String.equals()方法会返回true如果被操作的String对象的内容相同。
对于上面的代码会有s1==s2,因为s1和s2两个引用指向同一个对象,对于上面的代码,s3.equals(s4)会返回true因为两个对象的内容都一样为”hello”。
你可以从上图看出这种机制。
在这里有三个独立的包含了相同的内容(”hello”)的对象,实际上我们不需要这么三个独立的对象――因为要运行它们的话既浪费时间又浪费内存。
那么怎样才能确保String对象不会重复呢?
下一个话题会涵盖对于内建String机制的兴趣。
滞留字符串的优化作用
同一个字符串对象被重复地创建是不必要的,String.intern()方法可以避免这种情况。
下图说明了String.intern()方法是如何工作的,String.intern()方法检查字符串对象的存在性,如果需要的字符串对象已经存在,那么它会将引用指向已经存在的字符串对象而不是重新创建一个。
下图描绘了使用了intern()方法的字符串字面量和字符串对象的创建情况。
下面的例程帮助大家了解String.intern()方法的重要性。
StringTest2.java
packagecom.performance.string;
//Thisclassshowstheuseofintern()methodtoimproveperformance
publicclassStringTest2{
publicstaticvoidmain(String[]args){
//crea