美文网首页
StringBuilder和StringBuffer主要不同点简

StringBuilder和StringBuffer主要不同点简

作者: 老羊_肖恩 | 来源:发表于2021-11-15 15:49 被阅读0次

      众所周知,Java中String表示的字符串序列是不可变的,因此JDK提供了两种常用的可变字符序列的类,来实现字符序列的动态变化的功能。其中StringBuilder在多线程场景下是不安全的,如果需要在多线程同步的场景下安全操作可变字符序列,推荐使用StringBufferStringBuilderStringBuffer都是扩展了AbstractStringBuilder并实现CharSequence的,通过源码剖析,我们发现StringBuilderStringBuffer在实现上主要存在一下几点不同的地方。

    1.线程安全

      StringBuilderStringBuffer具体功能的实现,基本上都是调用父类AbstractStringBuilder的方法,最大的区别在于,所有涉及到线程安全保证的方法都使用到了synchronized关键字修饰,使用对象锁的方式来实现当前实例得线程安全。
    例如在StringBuilder中,append(Sting str)的方法实现如下:

        public StringBuilder append(StringBuffer sb) {
            super.append(sb);
            return this;
        }
    

      而在StringBuffer中,append(Sting str)的方法实现如下:

        @Override
        public synchronized StringBuffer append(String str) {
            toStringCache = null;
            super.append(str);
            return this;
        }
    

    2.toStringCache的使用

      StringBuilderStringBuffer还有一个最大的不同在于:StringBuffer定义了一个transient类型的临时变量toStringCache来缓存toString()当前的最新内容。该方法每次在调用toString()时,需要先判断toStringCache == null,因为每次在对当前的字符序列进行更新操作的时候,都会将toStringCache置为nullStringBuffer对象每调用一次toString(),都会将当前对象的字符序列内容拷贝一份到toStringCache中。

        /**
         * A cache of the last value returned by toString. Cleared
         * whenever the StringBuffer is modified.
         */
        private transient char[] toStringCache;
    
        public synchronized StringBuffer append(StringBuffer sb) {
            toStringCache = null;
            super.append(sb);
            return this;
        }
    
        @Override
        public synchronized String toString() {
            if (toStringCache == null) {
                toStringCache = Arrays.copyOfRange(value, 0, count);
            }
            return new String(toStringCache, true);
        }
    

      在调用toString()时将当前对象的字符序列内容拷贝一份到toStringCache中。有两个好处:1. 使用toStringCache通过共享一个char[]数组,提高构造String的速度。2. 连续多次调用toString()方法,是不需要重复调用Arrays.copyOfRange(value, 0, count),这样就不会产生多个内容相同的String对象的,因为 new String(toStringCache, true)返回的字符串,起内容会直接共享引用toStringCache,因为考虑到构建速度,目前String类中的该初始化方法暂不支持unshared模式,具体可以看一下String中的这个方法的实现。

        /*
        * Package private constructor which shares value array for speed.
        * this constructor is always expected to be called with share==true.
        * a separate constructor is needed because we already have a public
        * String(char[]) constructor that makes a copy of the given char[].
        */
        String(char[] value, boolean share) {
            // assert share : "unshared not supported";
            this.value = value;
        }
    

      但是toStringCache这些好处仅仅是在多次调用 toString()方法且当前的StringBuffer对象没有发生改变时才能体现。实际情况下,很少会在未修改StringBuffer的情况下重复调用StringBuffer对象的toString()方法,所以toStringCache并没有太大的实际作用。关于toStringCache存在 JDK 源码里的原因,有些人的解释是由于历史代码遗留的原因,保留它并没有什么坏处,修改了反而需要重新测试代码。
      至此,本文就简单介绍了一下StringBuilderStringBuffer的主要不同点,StringBuilderStringBuffer最大的不同点还是在于他们是分别为线程不安全和线程安全的场景下设计出来的改变字符序列的类,其他并没有什么本质的区别。在不考虑线程安全的情况下,推荐使用StringBuilder,因为性能会更好。

    相关文章

      网友评论

          本文标题:StringBuilder和StringBuffer主要不同点简

          本文链接:https://www.haomeiwen.com/subject/pflqtrtx.html