快捷搜索:  汽车  科技

string的底层实现是怎么样的(String底层详解)

string的底层实现是怎么样的(String底层详解)

String的底层实现原理

public final class String implements java.io.Serializable Comparable<String> CharSequence { /** The value is used for character storage. */ private final char value[]; 复制代码

可以看到 String 是被final所修饰的,这意味着String不可被继承 同样可以看到String的底层其实是一个char型的数组,同样被final修饰,变成了常量。 这里提一嘴fianl ,final可以修饰类,方法,变量 被fianl修饰的类不可被继承,被final修饰的方法不可被重载, 被fianl修饰的变量会变成常量,一经初始不可更改 复制代码String的赋值

String的运用有两种,一种是"=" 号直接赋值,另一种是new String("xxx")赋值 这两种是有区别的,首先说"="号赋值的这种 复制代码

String str = "abc"; 复制代码

"=" 号的赋值方式并不会在堆上创建新的对象,而是在常量池中搜索 如果常量池中有这个字符则直接引用这个字符的地址 如果没有这个字符,则会在常量池中创建该字符,并引用地址 字符常量池中不存在两个相同的字符,也就是说 复制代码

String str1 = "abc"; String str1 = "abc"; System.out.println(str1==str2);//true //二者引用的地址是相同的,都指向一个字符 复制代码

String str2=new String("abc"); 复制代码

new String() 意味着创建了一个新的对象,就意味着会在堆上分配一块内存 但并不是说这个字符就存储在了堆上,而是存储了一个地址,这个地址仍然指向字符常量池 有人说字符已经初始就不可更改了,那我要是像更改有什么办法嘛 复制代码

String str="abc"; System.out.println(str); System.out.println(str "456"); System.out.println(System.identityHashCode(str)); System.out.println(System.identityHashCode(str "456")); 输出结果: abc abc456 1528902577 1927950199 复制代码

可以看出虽然用" "号似乎可以增加新的字符,但是缺并不是原先的对象了,二者内存地址不同 而且也只能进行字符添加,要想修改字符的内容,就要看下面两个类了 复制代码StringBuffer和StringBuilder

这是我找到的一张关系图,可以看出 StringBuffer和StringBuilder都是继承自AbstractStringBuilder

string的底层实现是怎么样的(String底层详解)(1)

要想改变字符,StringBuffer和StringBuilder都为我们提供了一些方法 增加字符:append 方法 删除字符:delete 方法 反转字符:revers 方法 替换字符: replace 方法 还有一些其他方法就留着下回探索 复制代码

既然两个类都可以对字符进行修改,哪两者到底有什么区别呢?

StringBuffer是线程安全的,StringBuilder是非线程安全的 其实就是StringBuffer在一些方法加上了synchronized关键字加锁了 这样他就可以支持并发操作 在不考虑并发的情况下,StringBuilder的效率是要高于StringBuffer的 因为不需要加锁和释放锁 复制代码

扩容机制:

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable CharSequence { private transient char[] toStringCache; static final long serialVersionUID = 3388685877147921107L; public StringBuffer() { super(16); } 复制代码

可以看见,StringBuffer数组的初始长度是16(StringBuilder也是),当长度不够的时候, 会触发扩容机制,会创建一个新的数组,长度是原数组的二倍 2,再把原数组的元素复制过去 复制代码

private int newCapacity(int minCapacity) { // overflow-conscious code 扩大2倍 2 //这里可能会溢出 溢出后是负数哈 注意 int newCapacity = (value.length << 1) 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } //MAX_ARRAY_SIZE的值是Integer.MAX_VALUE - 8 先判断一下预期容量(newCapacity)是否在0<x<MAX_ARRAY_SIZE之间 在这区间内就直接将数值返回 不在这区间就去判断一下是否溢出 return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; }


作者:冷漠的麻辣烫
链接:https://juejin.cn/post/7018392166837780493
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜您喜欢: