String的原理及和StringBuilder区别

452次阅读
一条评论

本文主要讲述 String 和 StringBuilder 的区别,以及它们的内部实现原理。

1,String 的原理

public final class String
implements java.io.Serializable, Comparable, CharSequence,Constable, ConstantDesc {

@Stable
private final byte[] value;
.....

通过源代码我们可以看到 String 类内部使用了一个 final 修饰的 byte[] 字节码数组。当我们定义一个字符串,例如 String str = “abc“,实际上等价于 String str = new String(“abc”);。

String 类的构造函数会将接受到的字符参数,拆分成多个单独的字符,每个字符有它们对应的 Unicode,并被储存为字节,存到 byte[] 数组中。以 ”abc” 为例,在字节码数组中就是 {97,98,99}

2,String 的字符串拼接原理

第一点里我们说到,String 类内部的 byte[] 数组是 final 修饰的,所以 String 字符串本身就是不可变的。

所以当我们对 String 字符串进行拼接时,底层会直接创建一个新的 byte[] 字节码数组,然后将原先的字节数组和要拼接的字节数组拷贝到新数组,最终返回一个新的 String 对象。

不过 java 底层本身也会对字符串拼接进行一些优化。

String str1 = "abc" + "def";
// 底层优化
String str1 = "abcedf";

3,StringBuilder 与 String 区别

通过观察源代码,我们可以发现 StringBuilder 底层也是使用一个 byte[] 字节码数组用来储存字符,但与 String 不同的是,StringBuilder 创建字符串时,字节码数组默认预留 16 个字符空间,即字节码数组的长度是 字符串长度 + 16。

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);
}

同时 StringBuilder 类内部还有一个 count 成员变量,用来维护 StringBuilder 当前的字符总数

当我们使用 append 拼接字符串时,StringBuilder 会先判断字节数组的剩余容量是否够用(字节码数组长度 – 字符数 – 拼接的字符数),若长度足够,直接将新的字符插入到字节数组中,避免了频繁创建新数组带来的性能消耗;若容量不足,就会进行数组扩容操作,不过它不会像 String 类那样,创建一个新的对象。

public AbstractStringBuilder append(String str) {/*/
        if (str == null) {return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }

StringBuilder 容量判断和数组扩容

private void ensureCapacityInternal(/*/
int minimumCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        if (minimumCapacity - oldCapacity> 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }

综上所述,我们会发现,StringBuilder 在字符串拼接方面,有着比 String 类更好的性能优化。

如果你需要频繁的对数组进行增删改操作,我们通常建议是使用 StringBuilder,反之就是 String

String 的原理及和 StringBuilder 区别
正文完
 1
lujia
版权声明:本站原创文章,由 lujia 于2024-12-03发表,共计1773字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(一条评论)
Juggler 评论达人 LV.1
2024-12-03 22:46:48 回复

This is a Test.

 Windows  Edge  中国广东省广州市电信