前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >StringBuilder生产使用的一次事故

StringBuilder生产使用的一次事故

作者头像
猫老师的叶同学
发布2023-04-04 10:10:07
3730
发布2023-04-04 10:10:07
举报
文章被收录于专栏:中间件的探究中间件的探究

StringBuilder生产使用的一次事故

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

起因

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

验证

代码语言:javascript
复制
public class StringBuilderTest {
    
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder(null);
    }
}

执行结果如下:

在这里插入图片描述
在这里插入图片描述

到了这一步,基本算是复现了线上问题,确实是编码问题?那么为什么这样呢,明明append可以放入空指针对象呀? 深入源码查看,进入StringBuilder.java的带参构造器

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

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

解决方案

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

方法一:

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

代码语言:javascript
复制
public static void main(String[] args) {
    String obj = null;
    if (obj != null) {
        StringBuilder builder = new StringBuilder(obj);
    }
}
方法二:
代码语言:javascript
复制
public static void main(String[] args) {
    String obj = null;
    StringBuilder builder = new StringBuilder();
    builder.append(obj);
}

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

代码语言:javascript
复制
@Override
public StringBuilder append(String str) {
     super.append(str);
     return this;
 }

AbstractStringBuilder.java

代码语言:javascript
复制
/**
 * 将指定的字符串追加到此字符序列。将按顺序追加 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。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • StringBuilder生产使用的一次事故
    • 起因
      • 验证
        • 解决方案
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档