浅谈String、StringBuffer和StringBuilder

一. String

String 类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

String的实例化方式

  1. 通过字面量方式实例化

String str ="abc";
  1. 通过new+构造器的方式实例化

String str = newString("abc");

区别

  • 通过字面量方式为字符串赋值时,此时的字符串存储在方法区的字符串常量池中;

  • 通过new+构造器方式实例化字符串时,字符串对象存储在堆中,但是字符串的值仍然存储在方法区的常量池中。

String字符串具有不可变性,当字符串重新赋值时,不管是对字符串进行拼接,还是调用String的replace()方法修改指定的字符或字符串,都不会在原来的内存地址进行修改,而是重新分配新的内存地址进行赋值

二. StringBuffer

StringBuffer对象代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列,但都不会产生新的对象。通过StringBuffer生成的字符串,可以调用toString()方法将其转换为一个String对象。

StringBuffer是线程安全的

StringBuffer类中实现的方法,StringBuffer是如何实现线程安全的呢?

    @Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }

    /**
     * @since      1.5
     */
    @Override
    public synchronized void trimToSize() {
        super.trimToSize();
    }

从源码中可以看到,StringBuffer类中的方法都添加了synchronized关键字,也就是给这个方法添加了一个锁,用来保证线程安全。

三. StringBuilder

StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,他们的原理与操作一样,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

四. 总结

String、StringBuffer和StringBuilder三者的异同?

  • String :不可变的字符序列;底层使用 byte[] 存储。

  • StringBuffer :可变的字符序列;线程安全的,效率低;底层使用 byte[] 存储。

  • StringBuilder :可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用 byte[] 存储。

从代码角度验证三者的效率对比

接下我们来测试下拼接10000条数据的各自所耗的时间

package com.scg.springcloudordercenter.controller;

/**
 * @author gf
 * @date 2023/2/21
 */
public class StringTest {

    public static void main(String[] args) {

        long startTime;
        long endTime;
        String str1 = "";
        StringBuffer str2 = new StringBuffer("");
        StringBuilder str3 = new StringBuilder("");

        // 1.拼接str1,计算String所耗时间
        startTime = System.currentTimeMillis();
        for(int i= 1;i<=10000;i++){
            str1 += i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("String所耗时间为:" + (endTime-startTime) + "毫秒");

        // 2.拼接str2,计算StringBuffer所耗时间
        startTime = System.currentTimeMillis();
        for(int i= 1;i<=10000;i++){
            str2.append(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer所耗时间为:" + (endTime-startTime) + "毫秒");

        // 3.拼接str3,计算StringBuilder所耗时间
        startTime = System.currentTimeMillis();
        for(int i= 1;i<=10000;i++){
            str3.append(i);
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder所耗时间为:" + (endTime-startTime) + "毫秒");
    }

}

结果:


String所耗时间为:745毫秒
StringBuffer所耗时间为:4毫秒
StringBuilder所耗时间为:1毫秒

Process finished with exit code 0

很明显,我们拼接一万次字符串操作就可以对比出三者的效率:StringBuilder>StringBuffer>String

猜你喜欢

转载自blog.csdn.net/qq_44936392/article/details/129140878