阅读 297

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 在这里插入图片描述

要想改变字符,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


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐