String、StringBuilder、StringBuffer原理

本文深入探讨了Java中String、StringBuffer和StringBuilder的特性与效率差异,解析了它们的内部实现机制,强调了在不同场景下选择合适字符串类的重要性。

String

  不可变类, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String 。
举例:

	public static void main(String[] args){
		String s1 = "a";
		String s2 = "b";
		String s3 = "ab";
		String s4 = s1 + s2; 
		System.out.println(s3==s4);  // false
		return;
	}

原因是:String s4 = s1 + s2; 其底层是:

new StringBuilder().append("a").append("b").toString();

toString==》new String(“ab”);在堆里面
而s1,s2,s3都在常量池,所以不一样
如果是

String s5 = "a" + "b";
System.out.println(s3==s5);  //true

原因是,s5是由两个确定的值相加构成,s5的值就是确定的,javac在编译期间的优化,结果已经在编译器确定为ab,所以相等。

StringBuffer 和 StringBuilder 类

可变类

当对字符串进行修改的时候,特别是字符串对象经常改变的情况下,需要使用 StringBuffer 和 StringBuilder 类。

StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)

列出一部分源码,就能看出在源代码中StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。
StringBuilder源码

 @Override
    public StringBuilder append(char[] str, int offset, int len) {
        super.append(str, offset, len);
        return this;
    }

    @Override
    public StringBuilder append(boolean b) {
        super.append(b);
        return this;
    }

StringBuffer源码

@Override
    public synchronized void setLength(int newLength) {
        toStringCache = null;
        super.setLength(newLength);
    }

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @see        #length()
     */
    @Override
    public synchronized char charAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        return value[index];
    }

那么String为什么是不可变类?StringBuffer 和 StringBuilder为什么是可变类

查看源码
String:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    //构造方法
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
 }

StringBuilder和StringBuffer
他们都继承了AbstractStringBuilder
在AbstractStringBuilder中:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;
    ...
}

可以看出String中的value是常量(final)数组,只能被赋值一次。 而StringBuilder和StringBuffer就是普通的数组,所以String是不可变类,而StringBuilder和StringBuffer是可变类

三者的效率问题

如果不考虑线程安全,首选StringBuilder
大量字符串相加时,StringBuffer的append()效率远好于String对象的"+"连接

参照:https://blog.youkuaiyun.com/itchuxuezhe_yang/article/details/89966303

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值