Java中StringBuffer类和StringBuilder类的用法及区别

Java中StringBuffer类和StringBuilder类的用法及区别:

1、先思考一个问题:
如果我们在开发中,需要进行字符串的频繁拼接,会有什么问题?

因为java中的字符串是不可改变的,每一次拼接都会产生中间产物字符串。这样会占用大量的方法区内存,造成内存空间的浪费。


2、引入StringBuffer对象的使用

使用StringBuffer,字符串缓冲区对象,也是一个用来存字符串的对象,可以大量减少拼接浪费问题,因为StringBuffer中存储字符串的byte[] value是不带final修饰符的。这样的话,你就可以在原来的字符串基础上直接拼接字符串。

StringBuffer使用无参数构造方法时默认创建长度为16的byte[] value来存储字符串。

当你追加字符串时,长度不够时,StringBuffer对象底层会自动实现byte[]数组的扩容。


3、减少底层自动扩容的次数

我们知道数组的扩容效率是很低的,所以如何优化StringBuffer来存储字符串?

就是初始化的时候使用有参数构造函数,传长度过去,你得先预估一下需要长度多少合适,尽量减少StringBuffer在追加字符串时自动扩容的次数。

预估准确,减少扩容次数,提高程序效率。


测试代码:

public class Test01 {
     
    public static void main(String[] args) {
     
        String s1 = "hello";
        String s2 = "hello" + "world";
        //思考,上面这两行代码产生了几个对象?
        //3个,分别是"hello", "world", "helloworld", 其中"world"是中间产物,让s2指向"helloworld"的中间产物
        //这个中间产物"world"保存在方法区字符串常量池当中,它的值是不可变的,造成内存浪费

        //创建一个初始化容量默认为16的byte[]数组(字符串缓冲区对象,StringBuffer)
        StringBuffer buffer = new StringBuffer();
        //拼接字符串。以后拼接字符串统一调用append()方法
        buffer.append("aa");
        buffer.append(10);
        buffer.append(true);
        buffer.append(3.14);
        buffer.append(100L);
        buffer.append('d');

        //输出一个引用,自动调toString()方法
        System.out.println(buffer);

        //String存储字符串用的byte[] value是有final修饰的,赋值后不可改变的
        //而StringBuffer存储字符串用的byte[] value是没有用final修饰的,可以进行追加字符串,满了会自动扩容

        //因为数组的扩容效率较低,所以在初始化一个StringBuffer对象时应传一个容量参数
        //预估一下需要的大小,减少自动扩容的次数

        //上面测试打印已知buffer存的字符串:aa10true3.14100d
		
		//因为StringBuffer也是用来存字符串的,所以很多方法都是和String的方法一样的使用
        //StringBuffer的charAt(int index)跟String的charAt(int index)一样的用法
        System.out.println(buffer.charAt(0));  //输出:a
        System.out.println(buffer.charAt(15));  //输出:d
        //System.out.println(buffer.charAt(16));  //报错:StringIndexOutOfBoundsException,下标越界

        //StringBuffer的capacity()方法,length(),都是返回所存字符串的长度
        System.out.println(buffer.capacity());  //输出:16
        System.out.println(buffer.length());  //输出:16

    }
}

4、StringBuilder对象的使用

还有一个类也可以完成字符串拼接的问题,用法和功能跟StringBuffer差不多。

这个类就是StringBuilder。

那StringBuffer和StringBuilder有什么区别吗?

通过翻阅它们的源代码可知:
StringBuffer中的方法都带有:synchronized关键字。表示在多线程环境下运行是安全的。

StringBuilder中的方法都没有带synchronized关键字,表示多线程环境下运行是不安全的。

总结:
StringBuffer是线程安全的,StringBuild是非线程安全的。


测试代码和上面一样的使用:

public class Test01 {
     
    public static void main(String[] args) {
     

        //创建一个初始化容量默认也是为16的byte[]数组(字符串缓冲区对象,StringBuild)
        StringBuilder builder = new StringBuilder();
        //拼接字符串。以后拼接字符串统一调用append()方法
        builder.append("aa");
        builder.append(10);
        builder.append(true);
        builder.append(3.14);
        builder.append(100L);
        builder.append('d');

        //输出一个引用,自动调toString()方法
        System.out.println(builder);
    }
}

总结:

1、StringBuffer,字符串缓冲区对象,也是一个用来存字符串的对象,常用于字符串的拼接。

2、StringBuffer中存储字符串的byte[] value是不带final修饰符,而String里存储字符串的byte[] value是带了final修饰符的。

3、StringBuffer使用无参数构造方法时默认创建长度为16的byte[] value来存储字符串,长度不够时底层会自动扩容。

4、数组的扩容效率是不高的,所以我们使用时应该使用有参数的构造方法,预估一下需求需要的长度,减少自动扩容的次数,提高程序效率。

5、StringBuilder用法跟StringBuffer类似。

6、StringBuffer是线程安全的,StringBuild是非线程安全的。

7、StringBuild使用较多,虽然线程不安全,但有其他解决办法。


你可能感兴趣的:(Java,EE,java,StringBuffer,StringBuilder)