String,StringBuffer,StringBuilder的区别

String

String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

在这里插入图片描述

详细解释:

有两种情况:

  1. 如果你是String a = “aaa”; a = a + “bbb”,则会根据你字符串常量池是否有"aaabbb",有就不会新建,a存在栈中,作为引用,指向那个已经存在字符常量池里面的"aaa",没有就会在字符串常量池新生成一个"aaabbb".
  2. 如果你是String x = new String(“aaa”); 首先会在堆中生成一个new String(“aaa”)对象,然后还是根据你字符串常量池是否有"aaa",如果有则堆中只会创建一个new String(“aaa”)对象,如果没有则会在字符串常量池创建"aaa",然后拷贝一份到堆中,所以堆中总共创建了两个对象。所以这种情况可能是生成一个,也可能是生成2个。

如果有错恳求指正,勿喷,谢谢。

StringBuffer (线程安全)

StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而且在原来的对象中可以连接新的字符串。

StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

StringBuilder

StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

三者继承结构

在这里插入图片描述

三者的区别:

(1)字符修改上的区别(主要)

String:不可变字符串;

StringBuffer:可变字符串、效率低、线程安全;

StringBuilder:可变字符序列、效率高、线程不安全;

(2)初始化上的区别,String可以空赋值,后者不行,报错

①String
StringBuffer s = null;   
StringBuffer s = “abc”;   
②StringBuffer
StringBuffer s = null; //结果警告:Null pointer access: The variable result can only be null at this location
StringBuffer s = new StringBuffer();//StringBuffer对象是一个空的对象
StringBuffer s = new StringBuffer(“abc”);//创建带有内容的StringBuffer对象,对象的内容就是字符串”

小结:(1)如果要操作少量的数据用 String;

(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder(推荐使用)。

总结表格:

StringStringBufferStringBuilder
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量可变类,速度更快
不可变可变可变
线程安全线程不安全
多线程操作字符串单线程操作字符串

继续深入

String 源码注释

在这里插入图片描述

Stirng类表示字符串。所有 Java程序中的字符串,例如{@code “abc”},是作为该类的实例实现。

字符串是常量;它们的值在它们之后不能改变,创建。字符串缓冲区支持可变字符串。因为字符串对象是不可变的,它们可以被共享

StringBuffer

在这里插入图片描述

由上可以看出 StringBuffer 通过了synchronized关键字保证了线程的安全性,但是效率会降低,又由于StringBuffer不需要重新开辟新的空间进行重新指向等一系列操作,提高了IO的处理速度,比String快,但是在单机并发量不高的情况下,StringBuffer又因为是线程安全的所以处理速度会有所降低。

StringBuilder

在这里插入图片描述

StringBuilder提供了String的可变性,提供了内存的处理速度,相比StringBuilder去掉了synchronized关键字,提升了效率,降低了高并发时的安全性。

随便写写 可以不看

AbstractStringBuilder 为 StringBuffer的父类

StringBuffer调用父类的方法

public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }

AbstractStringBuilder 中的方法

// Documentation in subclasses because of synchro difference
    public AbstractStringBuilder append(StringBuffer sb) {
        if (sb == null)
            return appendNull();
        int len = sb.length();
        ensureCapacityInternal(count + len);
        sb.getChars(0, len, value, count);
        count += len;
        return this;
    }

// Documentation in subclasses because of synchro difference
    public AbstractStringBuilder append(StringBuffer sb) {
        if (sb == null)
            return appendNull();
        int len = sb.length();
        ensureCapacityInternal(count + len);   //第一个方法
        sb.getChars(0, len, value, count);  //  主要看第二个方法
        count += len;
        return this;
    }

/**
     * For positive values of {@code minimumCapacity}, this method
     * behaves like {@code ensureCapacity}, however it is never
     * synchronized.
     * If {@code minimumCapacity} is non positive due to numeric
     * overflow, this method throws {@code OutOfMemoryError}.
     */
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }



// 》》 sb.getChars(0, len, value, count);  //  主要看第二个方法

//  调用StringBuffer 中的方法,又通过Super()返回本类中调用

/**
     * Characters are copied from this sequence into the
     * destination character array {@code dst}. The first character to
     * be copied is at index {@code srcBegin}; the last character to
     * be copied is at index {@code srcEnd-1}. The total number of
     * characters to be copied is {@code srcEnd-srcBegin}. The
     * characters are copied into the subarray of {@code dst} starting
     * at index {@code dstBegin} and ending at index:
     * <pre>{@code
     * dstbegin + (srcEnd-srcBegin) - 1
     * }</pre>
     *
     * @param      srcBegin   start copying at this offset.
     * @param      srcEnd     stop copying at this offset.
     * @param      dst        the array to copy the data into.
     * @param      dstBegin   offset into {@code dst}.
     * @throws     IndexOutOfBoundsException  if any of the following is true:
     *             <ul>
     *             <li>{@code srcBegin} is negative
     *             <li>{@code dstBegin} is negative
     *             <li>the {@code srcBegin} argument is greater than
     *             the {@code srcEnd} argument.
     *             <li>{@code srcEnd} is greater than
     *             {@code this.length()}.
     *             <li>{@code dstBegin+srcEnd-srcBegin} is greater than
     *             {@code dst.length}
     *             </ul>
     */
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
    {
        if (srcBegin < 0)
            throw new StringIndexOutOfBoundsException(srcBegin);
        if ((srcEnd < 0) || (srcEnd > count))
            throw new StringIndexOutOfBoundsException(srcEnd);
        if (srcBegin > srcEnd)
            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值