关于String 和 StringBuffer、StringBuilder

闲话不多,先看一段代码

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都会被保留么?这么没逻辑的事情我居然没有怀疑过,有点汗颜

作者:FreeAquar
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/FreeAquar/p/2710758.html