StringBuilder生产使用的一次事故

StringBuilder生产使用的一次事故

使用Java实现较长逻辑的代码中,无可避免会创建众多的String对象,又是为了节省内存空间以及优化程序效率,会选择使用StringBuilder或者StringBuffer来代替String对象。

起因

项目部署后,NPE的次数变多了,且均在StringBuilder构造器中,这引起的项目维护人的重视!

验证

public class StringBuilderTest {
    
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder(null);
    }
}

执行结果如下:
在这里插入图片描述
到了这一步,基本算是复现了线上问题,确实是编码问题?那么为什么这样呢,明明append可以放入空指针对象呀?
深入源码查看,进入StringBuilder.java的带参构造器

    /**
     * 构造初始化为指定字符串内容的字符串生成器。字符串生成器的初始容量为 16 加上字符串参数的长度。
     * 参数:str – 缓冲区的初始内容。
     */
    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

到这里算是明白了,调用length()方法,所以会有空指针的异常,瞬间感觉这个错误很低级。

解决方案

基于以上问题,基本解决方案就是,避免传入NULL对象,或者使用append()

方法一:

对于使用StringBuilder构造器的对象,进行非空判断,例如:

public static void main(String[] args) {
    String obj = null;
    if (obj != null) {
        StringBuilder builder = new StringBuilder(obj);
    }
}
方法二:
public static void main(String[] args) {
    String obj = null;
    StringBuilder builder = new StringBuilder();
    builder.append(obj);
}

由于append在添加字符串时,会先进行判空并 替代塞入"null",所以这个方法不提倡。
那么它的源码是如何实现的呢?
StringBuilder.java

@Override
public StringBuilder append(String str) {
     super.append(str);
     return this;
 }

AbstractStringBuilder.java

/**
 * 将指定的字符串追加到此字符序列。将按顺序追加 String 参数的字符,使此序列的长度按参数的长度增加。
 * 如  果 str 为 null,则附加四个字符 “null”。设 n 是执行追加方法之前此字符序列的长度。则新字符序
 * 列中索引 k 处的字符等于旧字符序列中索引 k 处的字符,如果 k 小于 n;否则,它等于参数 str 中索引
 *  k-n 处的字符。
 * 参数:str – 一个字符串。
 * 返回:对此对象的引用。
 **/
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;
    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;
}

以上就是一次事故给自己的一些思考,优化可以,但是不可以多写bug。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值