浅析我对 String、StringBuilder、StringBuffer 的理解

网友投稿 334 2022-12-05


浅析我对 String、StringBuilder、StringBuffer 的理解

StringBuilder、StringBuffer 和 String 一样,都是用于存储字符串的。

1、那既然有了 String ,为什么还需要他们两个呢?

原因是 String 是不可变的,它每次的字符串拼接,实际上都会 new 一个新的 String 进行接收。

2、谈谈StringBuilder、StringBuffejbBwMmr他们两个的联系:

我们可以知道 StringBuffer 在 1.0 的时候就发布了,那为什么还需要 StringBuilder 呢?原因是它的大部分方法都上了锁,是线程安全的,导致了效率较低!而我们有时候不需要考虑线程安全问题,追求效率!所以 StringBuilder 在 1.5 的时候就出来了!

3、StringBuilder、StringBuffer 的异同:*

不同:

StringBuffer 它因为追求安全,给大量方法上锁,线程安全!

Strihttp://ngBuilder 它因为追求效率,没有给方法上锁,线程不安全!

相同:内部方法和 StringBuffer 完全一致,因为都继承了 AbstractStringBuilder,底层数组都是用父类的。

4、源码浅析 String:

结论:final 修饰了底层的字符数组,故内容不可变。

5、源码浅析 StringBuilder:构造方法

观察构造方法:

public StringBuilder() {

super(16);

}

public StringBuilder(int capacity) {

super(capacity);

}

public StringBuilder(String str) {

super(str.length() + 16);

append(str);

}

public StringBuilder(CharSequence seq) {

this(seq.length() + 16);

append(seq);

}

结论:可以看出,它有一个默认的长度 16!而当传入参数是一个字符或者字符串时,它也会自动的传入参数的长度上加上 16!

6、源码浅析 StringBuilder:append 方法

@Override

public StringBuilder append(Object obj) {

return append(String.valueOf(obj));

}

@Override

public StringBuilder appjbBwMmend(String str) {

super.append(str);

return this;

}

我们发现,它还是调用的父类的 append 方法,说明这个方法他并没有重写,那么 StringBuffer 也一样!

public AbstractStringBuilder append(String str) {

if (str == null)

return appendNull();

int len = str.length();

ensureCapacityInternal(count + len);

str.getChars(0, len, value, count);

count += len;

return this;

}

结论:我们可以看出,他也是可以拼接 null 的!

private AbstractStringBuilder appendNull() {

int c = count;

ensureCapacityInternal(c + 4);

final char[] value = this.value;

value[c++] = 'n';

value[c++] = 'u';

value[c++] = 'l';

value[c++] = 'l';

count = c;

return this;

}

然后观察,它接着进行了一个数组容量的判断,而数组的扩容,其实就是在里面实现的,我们点进去看一下!

private void ensureCapacityInternal(int minimumCapacity) {

// overflow-conscious code

if (minimumCapacity - value.length > 0) {

value = Arrays.copyOf(value,

newCapacity(minimumCapacity));

}

}

结论:它先是判断,当前数组容量+拼接字符 是否大于 数组长度,如果大于,则进行数组拷贝,并将底层数组的引用指向新数组!

private int newCapacity(int minCapacity) {

// overflow-conscious code

int newCapacity = (value.length << 1) + 2;

if (newCapacity - minCapacity < 0) {

newCapacity = minCapacity;

}

return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)

? hugeCapacity(minCapacity)

: newCapacity;

}

结论:由此可见,新数组长度扩容为原数组的 2倍+2 !

问题:那它究竟是怎么拼接字符串的呢?

sb.getChars(0, len, value, count);

进去看一下:String 的 getChars 方法

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

}

实际调用了一个系统类方法:arraycopy,再点进去看一下!

public static native void arraycopy(Object src, int srcPos,

Object dest, int destPos,

int length);

结论:底层最终是调用的本地方法,实现了的字符数组拷贝,但由于本地方法是可以和操作系统直接打交道的,所以它的 append 字符串拼接效率会高于 String!

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Boot加密配置文件特殊内容的示例代码详解
下一篇:Spring Boot如何优雅的使用多线程实例详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~