Java String StringBuilder StringBuffer

String

* UTF-16 类似于 UTF-8,在表示非 Latin1 字符时更加高效
* ISO 8859-1,又叫 Latin1,在 ASCII 字符集上添加了西欧字符
* value 字符数组,表示实际的字符串
* coder 整型变量,表示编码器,有 Latin1 和 UTF-16 两种
COMPACT_STRINGS 表示当前字符串是否使用 LATIN1 编码器,由 JVM 进行判断
@Native static final byte LATIN1 = 0;  // LATIN1 编码器的 coder 为 0
@Native static final byte UTF16  = 1;  // UTF16 编码器的 coder 为 1
    // 从虚拟机对数组的大小有限制上看,String 最长不能超过虚拟机可分配的空间最大值
    // 从方法签名上看,String 最长不能超过 int 的最大值,即 Integer.MAX_VALUE
    String(char[] value, int off, int len, Void sig) {
        if (len == 0) {
            this.value = "".value;
            this.coder = "".coder;
            return;
        }
        if (COMPACT_STRINGS) {
            byte[] val = StringUTF16.compress(value, off, len);
            if (val != null) {
                this.value = val;
                this.coder = LATIN1;
                return;
            }
        }
        this.coder = UTF16;
        this.value = StringUTF16.toBytes(value, off, len);
    }

* char 相当于无符号整数
* 与运算 0 与 1 为 0,1 与 1 为 1
* 0xff 等于 255 二进制表示是 8 个 1
* byte 类型的变量和 0xff 做 & 运算,相当于转为无符号整数
private static native boolean isBigEndian();  // 调用 c 或 c++ 库
    // 高 8 位 SHIFT
    static final int HI_BYTE_SHIFT;
    // 低 8 位 SSHIFT
    static final int LO_BYTE_SHIFT;
    // 运行时加载
    static {
        if (isBigEndian()) {
            HI_BYTE_SHIFT = 8;
            LO_BYTE_SHIFT = 0;
        } else {
            HI_BYTE_SHIFT = 0;
            LO_BYTE_SHIFT = 8;
        }
    }
    @IntrinsicCandidate
    // intrinsic performs no bounds checks
    static char getChar(byte[] val, int index) {
        assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
        index <<= 1;
        // 取出高字节
        return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
                      // 取出低字节,使用或运算进行合并
                      ((val[index]   & 0xff) << LO_BYTE_SHIFT));
    }
    public static String trim(byte[] value) {
        UTF-16 每个字符占两个字节,右移一位后可得实际字符数量
        int length = value.length >> 1;
        int len = length;
        int st = 0;
        while (st < len && getChar(value, st) <= ' ') {
            st++;
        }
        while (st < len && getChar(value, len - 1) <= ' ') {
            len--;
        }
        return ((st > 0) || (len < length )) ?
            new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
            null;
    }
public String trim() {
        String ret = isLatin1() ? StringLatin1.trim(value)
                                : StringUTF16.trim(value);
        // 如果字符串为 null 返回该对象,否则返回一个新字符串
        return ret == null ? this : ret;
    }
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        return (anObject instanceof String aString)
                && (!COMPACT_STRINGS || this.coder == aString.coder)
                && StringLatin1.equals(value, aString.value);
    }

StringBuilder

* 类似于 String 的可变对象,是线程不安全的

* StringBuilder 是如何将字符串对象转为 StringBuilder 呢?
    简单来讲:调用抽象类 AbstractStringBuilder 的构造方法,确定编码器,声明数组空间,
    进行复制
AbstractStringBuilder(String str) {
        int length = str.length();
        int capacity = (length < Integer.MAX_VALUE - 16)
                ? length + 16 : Integer.MAX_VALUE;
        final byte initCoder = str.coder();
        coder = initCoder;
        value = (initCoder == LATIN1)
                ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
        append(str);
    }
public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        /*
        count 表示当前字符串的字符数量
        */
        ensureCapacityInternal(count + len);  // 确保有足够的空间
        putStringAt(count, str);
        count += len;
        return this;
    }
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        /*
        value 子节数字,表示当前存储的字符
        */
        int oldCapacity = value.length >> coder;
        // 不够就扩容
        if (minimumCapacity - oldCapacity > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }
private void putStringAt(int index, String str) {
        putStringAt(index, str, 0, str.length());
    }
private void putStringAt(int index, String str, int off, int end) {
        if (getCoder() != str.coder()) {  // 可能会添加不同字符集的字符
            inflate();
        }
        // 进行复制
        str.getBytes(value, off, index, coder, end - off);
    }
void getBytes(byte[] dst, int srcPos, int dstBegin, byte coder, int length) {
        if (coder() == coder) {
            System.arraycopy(value, srcPos << coder, dst, dstBegin << coder, length << coder);
        } else {    // this.coder == LATIN && coder == UTF16
            StringLatin1.inflate(value, srcPos, dst, dstBegin, length);
        }
    }

StringBuffer

* 类似于 StringBuilder 是线程安全的可变对象,通过添加 synchronized 锁

* StringBuffer 是如何将 String 对象转为 StringBuffer 对象呢?
    和 StringBuilder 相同
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值