从源码底层来看String,StringBuffer,与StringBuild

String的底层

String类没有提供用于修改字符串的方法。String类对象为不可变字符串,不可变字符串有一个优点:编译器可以让字符串实现共享。实际上只有字符串常量(使用“ ”声明,存储在字符串常量池中)是共享的,比较字符串值是否相等时使用equals()方法,不能使用==,==比较的是字符串的地址是否相同。如果字符串在常量池中,可以使用

==比较,因为指向的都是同一个字符串。下面是String的源代码,可以看到,String类是final修饰的,然后还有个成员属性 value 它也是final的并且是一个char类型的数组,通过构造方法可以看到,我们传递的参数值 是直接赋值给了 value

那么我们说明 String它是一个不可变字符串,底层是一个char类型的数组

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
 
    private final char value[];
 
     private int hash; // Default to 0
 
    
    private static final long serialVersionUID = -6849794470754667710L;
    
    ......此处省略N多代码
    
    /**
     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.
     *
     * @param  original
     *         A {@code String}
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
 
}

直接使用” ”声明的String对象会直接存储在常量池中,(可以实现共享)

  1. String str1=”a”
    jvm在运行时先查找常量池中是否有该字符串,如果有则直接返回该字符串的引用给first(实现了字符串 的共享) ;否则先在常量池中创建该字符串并返回引用。此时只会在常量池中创建String对象,不会在堆中创建。
  2. String str2=new String(“b”); 该代码生成了两个String对象。因为使用了“”会现在常量池中查找是否存在second对象,没有则创建,否则不创建;在常量池创建完成后,由于使用了new,jvm会在堆中创建内容相同的String对象,并将引用返回给str2.
  3. String str3=”c”; String str4=str3+”d”;
    运行时,+ 相当于new,所以堆中会有“cd”对象;常量池中会有”c” “d”两个对象,而不会有”c d ”对象。

StringBuffer

继承

StringBuffer继承自AbstractStringBuilder

StringBuffer实现扩容

StringBuffer扩容的机制在抽象类AbstractStringBuilder中实现,当发现长度不够的时候(默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组。

public void ensureCapacity(int minimumCapacity) {
     if (minimumCapacity > 0)
         ensureCapacityInternal(minimumCapacity);
 }
 
 /**
 * 确保value字符数组不会越界.重新new一个数组,引用指向value
 */    
 private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

/**
* 扩容:将长度扩展到之前大小的2倍+2
*/    
private int newCapacity(int minCapacity) {
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }

    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}
/**
* 判断大小,是否溢出
*/
private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}

线程安全性

几乎都是所有方法都加了synchronized,几乎都是调用的父类的方法.,加锁,资源同步串行化处理,所以是线程安全的。

StringBuilder

@Override
public StringBuilder append(double d) {
    super.append(d);
    return this;
}

/**
 * @since 1.5
 */
@Override
public StringBuilder appendCodePoint(int codePoint) {
    super.appendCodePoint(codePoint);
    return this;
}

/**
 * @throws StringIndexOutOfBoundsException {@inheritDoc}
 */
@Override
public StringBuilder delete(int start, int end) {
    super.delete(start, end);
    return this;
}
  1. 方法中没有用synchronized修饰,线程非安全的字符串操作类

  2. 字符串的添加没有加同步处理,涉及到数组扩容,容易产生脏数据,破坏数据正确性

继承

StringBuilder继承自AbstractStringBuilder`类

扩容

因为继承了抽象类AbstractStringBuilder中实现,所以扩容与StringBuffer的扩容机制相同,当发现长度不够的时候(默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组。

执行速度

StringBuilder> StringBuffer > String

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值