java-Stringbuffer

java-Stringbuffer

文章首发于我的博客Lunatic,转载请注明出处


StringBuffer类的理解

继承关系图示

在这里插入图片描述

  1. java. lang String Buffer代表可变的字符序列,可以对字符串内容进行增删。

  2. 很多方法与 String相同,但 String Buffer是可变长度的。

  3. StringBuffer是一个容器。

  4. StringBuffer是一个final类,不可以被继承

  5. StringBuffer继承了AbstractStringBuffer类,而AbstractStringBuffer类里面维护了一个数组

    char[] value; //区别于String里面的数组,此数组没有final关键字,说明此数组是可以被更改的,也说明了此数组是在堆空间中的;不用每次都更换地址(即不是每次创建新对象),所以效率高于 String

StringBuffer底层源码分析

  1. StringBuffer类有四个构造方法:

    // 构造器一
    public StringBuffer() {
    }
    // 构造器二
    public StringBuffer(int capacity) {
    }
    // 构造器三
    public StringBuffer(String str) {
    }
    // 构造器四
    public StringBuffer(CharSequence seq) {
    }
    
  2. 使用构造器一创建对象

    public StringBuffer() {
        super(16);
    } // 调用父类的有参构造器,参数:16
    
    AbstractStringBuilder(int capacity) {
        value = new char[capacity]; // 此处参数传16,value指向一个char[],数组的初始大小为16
    } 
    
  3. 使用构造器二创建对象

    public StringBuffer(int capacity) {
        super(capacity); // 调用父类的有参构造器,参数:(构造方法中传进来的参数)
    }
    AbstractStringBuilder(int capacity) {
        value = new char[capacity]; //此处参数传16,value指向一个char[],数组的初始大小为自己指定的大小
    }
     // 此构造方法会开辟指定大小的数组长度
    
  4. 使用构造器三创建对象

    public StringBuffer(String str) {
        super(str.length() + 16); //调用父类的有参构造器,参数:该字符串的长度+16
        append(str); // 构建好char[]之后,调用append()
    }
    // 父类构造方法的调用2,3说过,此处不再说明
    
  5. 使用构造器四创建对象和构造器三差不多。

  6. 关于StringBuffer的底层扩容机制

    // 使用append()
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str); // 调用父类的append()
        return this;
    }
    
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len); // 此方法用来保证容量
        str.getChars(0, len, value, count);
        count += len; // count:用来记录字符的数量
        return this;
    }
    
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) { //如果需要的最小容量比数组的容量大,则开辟新数组
            value = Arrays.copyOf(value,
                                  newCapacity(minimumCapacity));
        }
    }
    
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2; //新开辟数组的容量是原数组容量的二倍加二
        if (newCapacity - minCapacity < 0) { 
            newCapacity = minCapacity; // 如果扩容之后还不够就直接扩容至所需要的容量
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
    
    

StringBuffer和String的区别

  1. String保存的是字符串常量,里面的值(地址值)不能更改,每次String类的更新实际上就是更改地址,效率较低

    private final char value;

  2. String Buffer保存的是字符串变量,里面的值可以更改,每次String Buffer的更新实际上可以更新内容,不用每次更新地址,效率较高

    char[] value; ∥这个放在堆.

StringBuffer和String的相互转换

  1. String -> StringBuffer

    String str = "hello tom";
    //方式1 使用构造器
    //注意: 返回的才是StringBuffer对象,对str 本身没有影响
    StringBuffer stringBuffer = new StringBuffer(str); 
    //方式2 使用的是append方法
    StringBuffer stringBuffer1 = new StringBuffer();
    stringBuffer1 = stringBuffer1.append(str);
    
  2. StringBuffer -> String

    StringBuffer stringBuffer3 = new StringBuffer("韩顺平教育");
    //方式1 使用StringBuffer提供的 toString方法
    String s = stringBuffer3.toString();
    //方式2: 使用构造器来搞定
    String s1 = new String(stringBuffer3);
    

StringBuffer类的常用方法

  1. append():添加元素
    说明:可以连续使用append()添加元素,使用println()输出的时候,输出的是字符串,因为它底层调用了toString(),返回了一个字符串对象

    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }
    
  2. delete()::删除元素

  3. replace():替换元素

  4. insert():插入元素

  5. length():获取StringBuffer中所含元素的个数

StringBuffer测试题

  1. 第一个
String str=null; 
StringBuffer sb= new StringBuffer(); 
    sb. append(str);
System. out. println(sb.length()); //4 
System.out.println(sb); // null  

底层源码分析

public synchronized StringBuffer append(String str) {
    toStringCache = null; 
    super.append(str); //调用父类的append();
    return this;
}

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull(); // 如果添加的字符串树null,则调用appendNull()
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;   // 将null每个字符添加进去
}

总结:StringBuffer使用append()添加null的时候,不会出现空指针异常的问题

  1. 第二个
StringBuffer sbl= new StringBuffer(str); // 会报空指针异常的错误
System. out. printIn(sbl) 

底层源码分析

  public StringBuffer(String str) {
        super(str.length() + 16); // 在调用父类构造器的时候会出现null.length(),这时候会出现空指针异常的问题
        append(str);
    }

总结:StringBuffer使用构造方法添加null的时候会出现空指针异常的问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艺术留白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值