#深度解析StringBuffer

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 深度解析

基本介绍

StringBuffer代表可变的字符序列,可对字符串内容进行增删,很多方法与String相同,但是StringBuffer是可变长度的

StringBuffer是一个容器

StringBuffer类图如下

从类图中可以看出

StringBuffer的直接父类 是 AbstractStringBuilder

StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化

在父类中 AbstractStringBuilder 有属性 char[] value,不是 final

该 value 数组存放 字符串内容,存放在堆中

StringBuffer 是一个 final 类,不能被继承

因为 StringBuffer 字符内容是存在 char[] value, 所以在变化(增加/删除) 时,不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String

String 和 StringBuffer 相互转换

首先看一下StringBuffer的构造器

package com.wxit.stringbuffer;

/**
 * @Author wj
 * StringBuffer学习,构造器的使用
 **/
public class StringBuffer01 {
    public static void main(String[] args) {
        //创建一个大小为16的char[],用于存放字符内容
        StringBuffer stringBuffer01 = new StringBuffer();
        
        //2.通过构造器指定char[]的大小
        StringBuffer stringBuffer02 = new StringBuffer(100);

        //通过给一个String 创建 StringBuffer,char[] 大小就是str.length + 16
        StringBuffer stringBuffer03 = new StringBuffer("hello");
    }
}

以上三个构造器对应的源码如下图

代码示例如下

package com.wxit.stringbuffer;

/**
 * @Author wj
 * String与StringBuffer相互转化
 **/
public class StringAndStringBuffer {
    public static void main(String[] args) {

        //String --> StringBuffer
        String str = "hello world";
        //方式一 使用构造器
        StringBuffer stringBuffer = new StringBuffer(str);
        System.out.println(stringBuffer);

        StringBuffer stringBuffer1 = new StringBuffer();
        StringBuffer append = stringBuffer1.append(str);
        System.out.println(append);

        //StringBuffer -->  String
        StringBuffer stringBuffer2 = new StringBuffer("即使再小的帆也能远航");
        //方式一 : StringBuffer提供的toString方法
        String s = stringBuffer2.toString();
        System.out.println(s);

        //方式二:使用构造器
        String s1 = new String(stringBuffer2);
        System.out.println(s1);
    }
}

StringBuffer方法

从类图中可以看出StringBuffer中有众多方法

以上只是部分方法,还不包括父类的方法

下面列举常用的方法

常用方法

代码示例

package com.wxit.stringbuffer;

/**
 * @Author wj
 * StringBufferMethod常用方法
 **/
public class StringBufferMethod {
    public static void main(String[] args) {
        StringBuffer buffer = new StringBuffer("你好");
        //增加
        buffer.append(",");
        buffer.append("吴杰");
        buffer.append("李婷").append("佳伟").append("子龙").append("子云").append("还有合一小家");
        System.out.println(buffer);

        //删
        System.out.println(buffer.delete(5,7));

        //改
        System.out.println(buffer.replace(4,6,"小昊"));

        //查找指定的子串在字符串第一次出现的索引,如果找不到返回-1
        System.out.println(buffer.indexOf("子云"));

        //插入  在索引为 0 的位置插入 "hello",原来索引为 9 的内容自动后移
        System.out.println(buffer.insert(0,"hello"));
    }
}

运行效果

StringBuffer练习

以下代码输出什么?为什么?

代码如下

package com.wxit.interview;

/**
 * @Author wj
 **/
public class Demo08 {
    public static void main(String[] args) {
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        System.out.println(sb.length());//4
    }
}

解析如下

首先 String str = null; 是成立的

然后进入到StringBuffer的源码中,查看append()方法,源码如下

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

从源码中看出StringBuffer中的append方法有调用了父类的append方法,所以,追进父类AbstractStringBuilder查看父类的append方法,源码如下

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

又str为空,所以又调用了appendNull()方法,追进appendNull()方法,代码如下

  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'

故最后输出的结果应该为4

练习二

代码如下

package com.wxit.test;

import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.util.Scanner;

/**
 * @Author wj
 * 练习
 * 需求:输入价格,要求,价格的小数点前面每三位就用一个逗号隔开
 **/
public class StringBufferDemo01 {
    public static void main(String[] args) {
        /*
        思路分析
        1.定义一个Scanner 对象,接收用户的价格(String)
        2.希望使用到StringBuffer中的insert方法,需要将String 转换成StringBuffer
        3.然后使用相关的方法进行字符串的处理
         */

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入价格");
        String price = scanner.next();
        System.out.println("输入的价格为:" + price);
        StringBuffer sb = new StringBuffer(price); //123456.789
        //先完成一个最简单的实现
//        System.out.println(sb.lastIndexOf("."));
        System.out.println(sb.insert(sb.lastIndexOf(".") - 3,","));
        //有上面可得出规律为,先找到小数点的索引位置,然后向该索引的前三个位置插入一个逗号,所以要做一个循环
        for (int i = sb.lastIndexOf(".") - 3;i > 0; i -= 3){
            sb.insert(i,",");
        }
        System.out.println(sb);
    }
}
相关文章
|
7月前
|
Java 编译器
符串拼接,什么时候用StringBuilder
符串拼接,什么时候用StringBuilder
38 0
|
7月前
|
Go
深度解析 ValueOf() 与 Value 的神奇魔法
深度解析 ValueOf() 与 Value 的神奇魔法
85 0
|
7月前
|
存储 安全 Java
【JAVA基础】String、StringBuilder和StringBuffer的区别——巨详细
String是不可变的,StringBuilder和StringBuffer是可变的。而StringBuffer是线程安全的,而StringBuilder是非线程安全的。
|
7月前
|
安全 API
详解StringBuilder和StringBuffer(区别,使用方法,含源码讲解)
详解StringBuilder和StringBuffer(区别,使用方法,含源码讲解)
139 0
|
存储 安全 Java
java StringBuilder 和 StringBuffer 万字详解(深度讲解)
java API专题——StringBuffer类和StringBuilder类。
148 0
java StringBuilder 和 StringBuffer 万字详解(深度讲解)
|
安全 Java
手把手实例对比String、StringBuilder字符串的连接效率及StringBuilder和StringBuffer线程安全的比较...
手把手实例对比String、StringBuilder字符串的连接效率及StringBuilder和StringBuffer线程安全的比较...
186 0
|
安全 Java 编译器
详细讲解String拼接原理,介绍StringBuilder和StringBuffer
详细讲解String拼接原理,介绍StringBuilder和StringBuffer
详细讲解String拼接原理,介绍StringBuilder和StringBuffer
|
存储 缓存 安全
ArrayList源码深度解析
ArrayList源码深度解析
91 0
ArrayList源码深度解析
|
存储 缓存 安全
|
安全 Java
【源码分析】String、StringBuffer、StringBuilder三者区别。
String 底层实际上是由 char 数组构成的,而且有 final 关键字修饰,这说明 String 类型的对象是不可以改变的,也是不可以被继承的。原始字符串永远不会更改。而是复制一份,并将要连接的文本被添加到复制的字符串之后,最后返回一个新的字符串。对大量字符串进行操作时 String 类可能会导致严重的内存泄漏和时间延迟。
【源码分析】String、StringBuffer、StringBuilder三者区别。