java22(String,StringBuffer与StringBuilder)

String(字符串):

       在 Java 中String属于对象,Java提供了String类来创建和操作字符串。明哥查找了一下jdk文档,发现String对象是不可被改变的(因为有“final”修饰符)

13091615-47301cf2c16568dd.png

        那么问题就来了:为什么java中字符串要被设计成不可变对象?

为什么String被设计成不可变对象?

    1.字符串常量池的需求

        字符串常量池是方法区中的一块特别存储区域。当需要创建一个字符串时,如果它的值在字符串常量池中已存在,那么常量池中的该字符串引用将被直接返回,而不会创建一个新的字符串对象返回其引用。

13091615-06894f69cec99f24.png

        如果字符串是可变的,那么通过一个引用改变字符串的值,其它该字符串对象的引用将得到错误的值。

    2.缓存Hashcode

        字符串的hashcode在java中经常被使用,如HashMap。不可变保证了hashcode会一直相同,所以它可以缓存起来而不需要担心改变。这也意味着,每次使用String的时候,不需要重新计算hashcode,这使得性能更加有效,所以我们经常会看到map的key使用字符串。

    3.线程安全

        因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。

例1:

13091615-f88237580a815eca.png

        更多String类支持的方法

StringBuffer和StringBuilder :

        当对字符串进行修改的时候,需要使用StringBuffer和StringBuilder类。和String类不同的是StringBuffer和 StringBuilder类的对象能够被多次的修改,并且不产生新的未使用对象。

        StringBuilder类在Java5中被提出,它和StringBuffer之间的最大不同在于StringBuilder的方法不是线程安全的(不能同步访问)。

        由于StringBuilder相较于StringBuffer有速度优势,所以多数情况下建议使用StringBuilder类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

        Java StringBuffer 和 StringBuilder 类手册

三者间的区别:

        我们每次对String类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,如下图所示,这种情况下如果jvm中的GC(垃圾回收机制)没有回收的话,内存中已经产生了一万多个对象

13091615-c27ee7e8a44acf1c.png

        而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下

        StringBuilder与StringBuffer 相比,二者之间有公共父类AbstractStringBuilder(抽象类)。因此二者间很多方法都是公用的,只是StringBuffer会在方法上加synchronized关键字,进行同步。因此通常来说应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。但是如果将 StringBuilder 的实例用于多个线程是不安全的。需要这样的同步,则建议使用 StringBuffer 。

总结:

    1.可变与不可变

        String对象不可变 StringBuilder与StringBuffer可变

    2.是否多线程安全

        String,StringBuffer线程安全,StringBuilder线程不安全

猜你喜欢

转载自blog.csdn.net/weixin_34221112/article/details/87054202