String、StringBuffer与StringBuilder之间区别(源码分析)

string:不可变字符串,每次修改都回生成一个新的变量,浪费内存
StringBuilder:可变字符串 线程不安全,单线程操作效率高
StringBuffer:可变字符串 线程安全


package com.example.spring;

/**
 * @Author: hyh
 * @Date: 2022/2/22 14:57
 **/
public class Test003 {
    public static void main(String[] args) {
     
        // 将 s1s1s1 放在常量池中 并返回引用
        String s1 = "s1s1s1";
        // 常量池中有 s1s1s1  直接返回引用
         String s2 = "s1s1s1";
         // 在堆内存开辟一块内存 并将该内存的value 值 指向常量池中的 s1s1s1
        String s = new String(s1);
        // 常量池中没有 在常量池中生成 333 并返回引用
        s1 = "333";

        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("123");
        StringBuffer append1 = stringBuffer.append("123");
        StringBuffer append2 = append1.append("321");
        // append1 地址和 append2 地址是一样的
        System.out.println(append1 == append2); // true
        
        StringBuffer stringBuffer1 = new StringBuffer(16);
        StringBuffer stringBuffer2 = new StringBuffer("123");

        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder1 = new StringBuilder(16);
        StringBuilder stringBuilder2 = new StringBuilder("456");
        stringBuilder.append("456");
    }
}

// String 源码
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
   
    // final 数组
    private final char value[];
    
    // 当 new 一个字符串时 实际给的时value 数组,而且时final 修饰,不可更改
    public String() {
        this.value = "".value;
    }
    
    //  第一次 stringBuilder.append("456"); srcBegin = 0, srcEnd = 3, dst[] = value[], dstBegin = 0
    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        // str.getChars(0, len, value, count); 由于调用的是 str 所以此时的value 就是str 的value  str = "456"
        // 将 str = "456"  从0 开始  复制到  dst = value[] 从0 开始 复制 3 - 0 = 3 个元素
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }
}
// StringBuffer 源码 父类是 AbstractStringBuilder
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{
        
    // 
    private transient char[] toStringCache;
    
    // new StringBuffer();
    public StringBuffer() {
        // 调用父类方法 并给初始大小为16
        super(16);
    }
    // new StringBuffer(16);
    public StringBuffer(int capacity) {
        super(capacity);
    }
    // new StringBuffer("123");
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
    
    //  synchronized 该方法被加同步锁了 这也是线程安全的原因,后面和 Stringbuilder.append() 方法几乎一样
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    
}
// StringBuilder  StringBuffer 的父类
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
    // 数组 没有final修饰
    char[] value;

    // 存储元素的个数 实际元素数量
    int count;


    AbstractStringBuilder() {
    }

     // 调用父类方法 并给初始大小为16
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
    // append 方法
    public AbstractStringBuilder append(String str) {
        // 追加字符串为 null 直接返回
        if (str == null)
            return appendNull();
        // 第一次 stringBuilder.append("456"); len = 3
        int len = str.length();
        // 第一次 count = 0  len = 3
        ensureCapacityInternal(count + len);
        // 调用 String类 的 getChars() 方法
        str.getChars(0, len, value, count);
        // 此时 value[] 已经被复制了 456 元素  count = 0+3  此时表示 value 数组实际有3个元素
        count += len;
        // 返回当前对象
        return this;
    }
    
    private void ensureCapacityInternal(int minimumCapacity) {
        // 第一次 value 初始化大小为 16  3-16 < 0 不进入方法
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
}
// StringBuilder 源码 父类是 AbstractStringBuilder
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence{

    // new StringBuilder() 和 new StringBuffer() 一样
    public StringBuilder() {
        super(16);
    }
    // new StringBuilder(16);
    public StringBuilder(int capacity) {
        super(capacity);
    }
    // new StringBuilder("456");
    public StringBuilder(String str) {
        // 调用父类方法 并传入初始大小 为 3("456")+ 16
        super(str.length() + 16);
        append(str);
    }
    
    @Override
    public StringBuilder append(String str) {
        // 调用父类方法 第一次 stringBuilder.append("456");
        super.append(str);
        return this;
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值