String、StringBuffer、StringBuilder

提到String、StringBuffer和StringBuilder大家都不陌生,在javase或多或少有过接触,但你真正了解它们之间的联系与区别吗?在面试中也是会被常常问道的题目,如果你有疑惑,或许我整理的文章可以帮到你!

目录

String类的特点

StringBuffer类的特点

StringBuilder类的特点

StirngBuffer与StringBuilder的扩容机制

String和StringBuffer、StringBuilder三者的比较

String和StringBuffer、StringBuilder三者的选择


String类的特点

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
 {...}
  • String类是一个final修饰的类,不能被继承

  • String实现了java.io.Serializable接口:表示字符串是支持序列化的

  • String实现了Comparable接口:表示String可以比较大小

  • String类存储数据使用的是一个final修饰的char数组,char数组的地址值不能改变。(jdk8及以下版本使用的底层是使用char数组,jdk9及以上底层是使用的byte数组

  • String存储的是不可变字符序列(字符串常量),值是不能改变的。每次修改都会在常量池中创建一个新的字符串,效率较低。

  • 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中

  • 字符串常量池中是不会存储相同内容的字符串

  •    @Test
        public void  testSting(){
            //字面方式建立字符串,使用intern()方法可以返回对象字符串在常量池中的地址
            String a="abc";
            String b="abc";
            System.out.println(a.intern()==b.intern());
           //因为new方式建立对象,即是内容是相同的,他们的对象地址也是不同
            String a1 = new String("abc");
            String b1 = new String("abc");
            System.out.println(a1==b1);
        }

    运行结果:

  • true
    false

StringBuffer类、StringBuilder类的特点

public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuffer>, CharSequence
{...}
public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
{
  • StringBuffer类、StringBuilder类也都实现了java.io.Serializable接口和Comparable接口,与上String相同

  • StringBuffer类、StringBuilder类都继承AbstractStringBuilder类

  • StringBuffer类、StringBuilder类都被final修饰,所以其不能被其他类继承的

  • StringBuffer类、StringBuilder类底层都是使用char数组存储字符串(jdk8及以下版本使用的底层是使用char数组,jdk9及以上底层是使用的byte数组

  • StringBuffer类、StringBuilder类存放的字符串是可以改变的,初始容量是16,当我们追加修改,或者是在构造时的容量超过了16,底层会自动扩容。

  • StringBuffer类、StringBuilder类继承了AbstractStringBuilder类,当然也重写了其中的方法,但其实这些重写的方法有的还是会调用 AbstractStringBuilder 中的公共方法。利用super.父类方法去调用父类的方法。

  • StringBuilder类线程不安全,区别于StringBuffer的线程安全

  • StringBuilder效率比StringBuffer快,单线程的时候优先考虑使用

StirngBuffer与StringBuilder的扩容机制

StringBuffer类、StringBuilder类存放的字符串是可以改变的,初始容量是16,当我们追加修改,或者是在构造时的容量超过了16,底层会自动扩容。

有参和无参扩容方法都一样的。都是从当前容量开始扩容 

当我们追加长度超过当前数组容量的时候,默认情况下,会按照 当前容量的2倍多2进行 扩容
当进行默认情况的扩容任然不够时,这时候会将容量直接扩容到与所添加的字符串长度相等的长度。

扩容原理是:底层会新建一个扩容后长度的新数组,并把原有数组中的元素复制到新的数组中返回。

    @Test
    public void testStringBuffer(){
        StringBuffer s = new StringBuffer();
        // 使用 capacity()方法可以查看当前容量、length()方法查看当前字符个数
        System.out.println("capacity:"+s.capacity()+"------- length:"+s.length());

        //追加长度为17时,超过了默认长度16,会按默认情况自动扩容
        s.append("12345678901234567");
        System.out.println("capacity:"+s.capacity()+"------- length:"+s.length());


        //追加长度超过当前容量的2倍多2个容量时,默认情况扩容也剩不下,会直接扩容到字符串的长度
        s.append("sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss");
        System.out.println("capacity:"+s.capacity()+"------- length:"+s.length());
    }

运行结果:

capacity:16------- length:0
capacity:34------- length:17
capacity:90------- length:90

String和StringBuffer、StringBuilder三者区别

相同点:

  • 三者都是用来存储字符串。

不同点:

  • String保存的是字符串常量,值不能被更改。每次更新字符串,实际上是更新了地址值

  • String使用的是final修饰的char型数组保存数据,代表不可变的字符序列。简称:不可变性

  • String的效率低,但是复用率高。

  • StringBuffer保存的是字符串变量,值可以更改,

  • 底层数组的初始容量是16,修改值时不会每次都更新地址,增加和删除字符串的内容时,效率较高。

  • StringBuffer是线程安全的,但效率低

  • StringBuilder虽然线程不安全的,但效率最高。

三者在运行时的效率:StringBuilder(单线程) > StringBuffer(线程安全) > String(不可变的字符序列)

String和StringBuffer、StringBuilder三者如何选择

  • 如果字符串存在大量的修改和删除操作,使用StringBuffer或StringBuilder

  • 如果字符串很少修改,同时被多多个对象引用,比如配置信息等,使用String

  • 如果在单线程的情况中,使用效率高的StringBuilder

  • 如果是多线程的清空中,使用线程安全的StringBuffer

结语

如果您在阅读文章发现了错误,还望您能及时联系我予以斧正,在这里先拜谢了!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值