String、StringBuffer、StringBuilder之间区别

  • String所声明的对象不可改变。在1.7之后,String的主要属性就是valur[],如下图所示,声明为private ,且没有相应的Set方法,所以在String的外部不能够修改String,也就是说一旦初始化之后就不能够改变值,且声明为final,也就是说一旦声明之后,String就是不能改变的了。因为String是不可修改的,所以安全性最高。
  • StringBuffe。正是因为String是不可修改的,所以每次修改时,都会新增一个String的对象,所以比较浪费资源,于是就有了StringBuffer的出现,它利用append()方法来实现字符串的改变,且所有方法都加了synchronized关键字,能够保证线程的安全性,但是也相应的性能降下来,于是就有了StringBuilder
  • StringBuilder。相对StringBuffer,去掉了关键字,所以性能大大提升,但是不是线程安全的。
  • 综上:
    • 线程安全性:String>StringBuffer>StringBuffer
    • 性能方面:StringBuilder>StringBuffer>String
    • 若所使用的字符串改动量不大,或者不经常使用,可以使用String;
    • 如需要频繁的更改字符串,在多线程场景下,则可考虑StringBuffer;
    • 如需要频繁的更改字符串,在单线程场景下,则可考虑StringBuilder;
    • 最后搞个String的小例子:
      String s = "ABCabc";
      System.out.println("s = " + s);
      s = "123456";
      System.out.println("s = " + s);

      结果是:

      ABCabc
      123

      首先创建一个String对象s,然后让s的值为“ABCabc”, 然后又让s的值为“123456”。 从打印结果可以看出,s的值确实改变了。那么怎么还说String对象是不可变的呢? 其实这里存在一个误区: s只是一个String对象的引用,并不是对象本身。对象在内存中是一块内存区,成员变量越多,这块内存区占的空间越大。引用只是一个4字节的数据,里面存放了它所指向的对象的地址,通过这个地址可以访问对象。 也就是说,s只是一个引用,它指向了一个具体的对象,当s=“123456”; 这句代码执行过之后,又创建了一个新的对象“123456”, 而引用s重新指向了这个心的对象,原来的对象“ABCabc”还在内存中存在,并没有改变。内存结构如下图所示

    • 再看一段代码:

       String b = "qwe";
              System.out.println(b);
              b.replace("w","g");
              System.out.println(b);

      执行结果

      qwe
      qwe

      再次证明了String对象不可修改。不过网上说反射可以进行更改,感兴趣的可以看看。

123456

原文地址:https://www.cnblogs.com/codehero/p/13611015.html