闲话不多,先看一段代码
public class test { public static void main(String[] args) { String str1 = "hello"; //方法1 String str2 = "hel"+"lo"; //方法2 String str3 = "hel"; str3 = str3 + "lo"; System.out.println("str1 == str2 :" + (str1 == str2)); System.out.println("str1 == str3 :" + (str1 == str3)); } }
结果会是什么呢,你们可以先猜猜
---------------------------------------我是分割线----------------------------------------------------
答案:
str1 == str2 :true
str1 == str3 :false
对于str2,jvm会自动帮你优化成
str2 = "hello";
首先,要注意一点,上面程序中的==并不表示比较内容,它们的值是指向对象所在的内存地址,而不是对象本身,而真正的比较内容是用的equal函数。
那他们相等的缘由,就一定是因为str1与str2所指向的地址。
当执行String str1 = "hello";
真正发生的事情,我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以
当继续执行String str2 = "hello";(优化后语句)时并不是new的一个字符串,此时并没有第二个对象产生,str2还是指向原来那个对象,也就是,和str1指向同一个对象。
ok地址相同了,自然返回true。
str3 =str3+"lo";
实际上是:
str3 = (new StringBuilder()).append(str3).append("lo").toString();
显然,str3是new出来的
要注意一点的是,String是不可变类,也就是说执行这个语句的时候,并不是说在原来的对象后面加上lo,而是说重新生成了一个新对象"hello",str3成为这个新对象的引用对象,而最重要的问题是,原先的"hel"依然存在。
好的,现在你一定在想,能不能有个好点的办法?有!
StringBuffer对象代表一个字符序列可变的字符串,当一个StringBuffer创建后,通过StringBuffer提供的一些方法可以改变这个字符串对的字符序列,一旦通过StringBuffer生产了最终想要的字符串,调用toString()方法即可将其转换为一个String对象
而StringBuilder是从jdk1.5后出现的,使用基本同StringBuffer,不同点是StringBuffer是线程安全的,但性能略低,StringBuilder反之
关于其简单的用法,盗用一下李刚老师的疯狂Java讲义里面的代码吧:
/** * Description: * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a> * <br/>Copyright (C), 2001-2012, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class StringBuilderTest { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); //追加字符串 sb.append("java");//sb = "java" //插入 sb.insert(0 , "hello "); //sb="hello java" //替换 sb.replace(5, 6, ","); //sb="hello, java" //删除 sb.delete(5, 6);//sb="hellojava" System.out.println(sb); //反转 sb.reverse();//sb="avajolleh" System.out.println(sb); System.out.println(sb.length()); //输出9 System.out.println(sb.capacity()); //输出16 //改变StringBuilder的长度,将只保留前面部分 sb.setLength(5); //sb="avajo" System.out.println(sb); } }
还有一个比较有意思的效率的帖子:赞里面的大神 ChDw(米)
http://topic.csdn.net/t/20050610/10/4072734.html
最近笔试比较多,刚好和同学讨论的时候(他是Java方向),又聊到一个东西,即有一个很大的程序运行时候,两个申请相同的字符串的String距离比较远的话却又不相等了后来被告知是因为jvm中有一个缓冲区,每次当新生成一个String的时候,他就会在自己的缓冲去里面找,当工程足够大的时候,原先申请的缓冲区里面已经没有之前那个String了,故他们不相等。
当了解到这些的时候,突然觉得自己思维有点死了,一直没问过自己,当程序很大的话,难道所有申请过的String都会被保留么?这么没逻辑的事情我居然没有怀疑过,有点汗颜