append方法的追踪(课堂复现)

append方法的追踪(课堂复现)

将原有的字符串扩展,或是进行不同字符串之间的拼接,往往很容易想到在两个字符串之间直接用“+”号运算来达到目的,而在java中这样的方法会残留些不必要的内容,而推荐使用Stringbuilder或StringBuffer中的append()方法,以下就以StringBuffer为例

public class FeiWuTest {
    public static void main(String[] args) {
        String s1 = "Wo ";
        String s2 = s1 + "shi ";
        String s3 = s2+"Fei";
        String s4 = s3+"wu";
        System.out.println(s4);
//这里会比下面多存在"Wo shi "、"Wo shi Fei"从而浪费空间


        StringBuffer sb1 = new StringBuffer("Wo ");
        sb1.append("shi ");
        sb1.append("Fei");
        sb1.append("wu");
        System.out.println(sb1);
    }
}

以第一个append为例

首先构造的一个sb1这个对象

public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}

调用父类构造

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

即构建出一个长度为输入字符串的长度+16,这里我写入的是”Wo “,所以对用传入的长度为19.(如果没有传入字符串,对应构造方法,传入的长度为16)

进入 append()方法,这里是构建第一个对象sb1时append

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

其中

private transient char[] toStringCache;

super.sppend(str);调用父类AbstractStringBuilder的append方法,其中str="Wo "

public AbstractStringBuilder append(String str) {
    if (str == null)//flase
        return appendNull();
    int len = str.length();//len=19
    ensureCapacityInternal(count + len)
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

其中

int count;//未赋值,默认为零

进入ensureCapacityInternal()传入的参数值为19

这里就开始了扩容操作

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {//true
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

其中value

char[] value;

value = Arrays.copyOf(value,newCapacity(minimumCapacity));

这是"类名."的方式调用,括号内newCapacity(minimumCapacity)大概最后还是返回这个minimumCapacity,也就是19

具体代码

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;
}

看到copyOf()方法

public static char[] copyOf(char[] original, int newLength) {
    char[] copy = new char[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

里面的arrycopy就不用说了,就是将传进来的字符数组复制一份给了copy这个数组然后返回,到这里AbstractStringBuilder的append方法中的value就被赋值了

之后的这个 str.getChars(0, len, value, count);在上一篇博文中也提到了,主要就是将这个value给赋值出来

最后两次return

至此”Wo “就被传入了sb1这个对象中,也就是构建出了一个StringBuffer对象sb1

现在我们进去测试类中的第一个append方法

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

这里传入的str也就是”shi “

这里append方法跟上面构建是的方法是一样的

public AbstractStringBuilder append(String str) {
    if (str == null)//flase
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

又是一步一步调用,确定字符串应该扩容的长度,然后经历getChats等直到用arraycopy将新传入的字符串复制到了原有字符串的后面,从此对象sb1的内容成了”Wo shi “,之前的”Wo “就没有东西指向了,而到了第二次append(“Fei”);就使sb1的内容变成了”Wo shi Fei“,之前的”Wo shi “就也没有了谁去指向就被回收了。

而相反使用”+“这样的方法,之前几次组合的字符串都有被指向,一直不会消失,如果多次使用这样的方式拼接,有很大的弊端。

最后将输出结果也贴一下吧

public class FeiWuTest {
    public static void main(String[] args) {
        String s1 = "Wo ";
        String s2 = s1 + "shi ";
        String s3 = s2+"Fei";
        String s4 = s3+"wu";
        System.out.println(s4);



        StringBuffer sb1 = new StringBuffer("Wo ");
        sb1.append("shi ");
        sb1.append("Fei");
        sb1.append("wu");
        System.out.println(sb1);
    }
}


/*
Wo shi Feiwu
Wo shi Feiwu

Process finished with exit code 0
*/

这篇也就是粗略地回忆一下讲过的这玩意

至于System.out,println这玩意有兴趣可以看看我上篇的”瞎撞“

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值