String,StringBuilder,StringBuffer区别

String,StringBuilder,StringBuffer区别

1.练习

public static void main(String[] args) {

    String str1 = "xxxx";                        //1
    String str2 = "xxxx";                      
    String str3 = new String("xxxx");    		//3
    String str4 = "" + str1;                    //4
    String str5 = new String("xxxx").intern();  //5

    System.out.println(str1 == str2);
    System.out.println(str1 == str3);
    System.out.println(str1 == str4);
    System.out.println(str1 == str5);
}

运行结果:

true
false
false
true

2.说明

  • String类中真正存储字符串的是一个char[]数组,并且是final修饰的,这也就是String类不可变的根源;

  • 字符串的字面量会保存在常量池中,不管以第一行还是第三行实例化字符串对象,在常量池中只有一个"xxxx"

  • 通过new String(“xxxx”)方式实例化对象时,会在虚拟机堆上创建对象,也就是说str3指向的是堆上对象的引用,str3中的char[]指向的是常量池中的“xxxx”,而str1对象中的char[]直接指向的是常量池中的"xxxx"

  • 第四行原理与第三行类似,在堆上创建对象

  • intern()方法会将字符串添加到常量池中,前提是当前常量池中不存在

3.原理分析

3.1 StringBuffer与StringBuilder

特点是字符串可变,均继承自抽象类AbstractStringBuilder,字符串保存在AbstractStringBuilder类的char[]数组中,注意没有final修饰,区别在于StringBuffer线程安全,StringBuilder线程不安全。StringBuffer之所以线程安全是因为对字符串操作的方法加了synchronized关键字修饰,因此效率会低一点,对于不存在多线程操作的字符串来说,推荐使用StringBuilder。具体源码实现方面二者基本一致,下面以StringBuilder分析,StringBuffer类似,其实主要是char[]的动态扩容机制,这种机制在集合,map中也有用到

3.2 StringBuffer源码分析

从StringBuffer的无参构造器开始

public StringBuilder() {
    super(16);  //无参构造器数组长度16
}

再看两个有参构造器。

public StringBuilder(int capacity) {
    super(capacity);
}
public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

在实例化StringBuffer时会调用父类的构造方法,它的父类AbstractStringBuilder

AbstractStringBuilder(int capacity) {
    value = new char[capacity];   //底层实例化一个char[]数组value,
}

以append()方法为例,说明数组扩容。

public StringBuilder append(String str) {
    super.append(str);  //调用父类方法
    return this;
}

AbstractStringBuilder类中的append方法:

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    //count表示当前数组中字符的个数,也就是字符串的长度。
    ensureCapacityInternal(count + len);  //执行扩容
    str.getChars(0, len, value, count);  //将str内容添加到数组中
    count += len;
    return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
    // 追加后的长度大于value.length的话,扩容
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));  //这里会创建一个新的数组,新数组中的内容还和原数组一样
    }
}
private int newCapacity(int minCapacity) {
    //扩大为原来的2倍加2
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {  //扩大后2倍加2后还是不够
        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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值