龙空技术网

String底层详解

Java老油条 399

前言:

现在小伙伴们对“string创建java”都比较关心,你们都想要知道一些“string创建java”的相关知识。那么小编也在网上搜集了一些对于“string创建java””的相关内容,希望大家能喜欢,咱们快快来了解一下吧!

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"));输出结果:abcabc45615289025771927950199复制代码
可以看出虽然用"+"号似乎可以增加新的字符,但是缺并不是原先的对象了,二者内存地址不同而且也只能进行字符添加,要想修改字符的内容,就要看下面两个类了复制代码
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;}

作者:冷漠的麻辣烫

链接:

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签: #string创建java