String、StringBuffer和StringBuilder的区别

String、StringBuffer和StringBuilder的区别

我们为什么要引入StringBuffer和StringBuilder?

String的局限性:

String不是基本数据类型,在创建的字符串属于对象,一种是new()创建对象,一种是创建String类对象的引用变量。
但是,String是被final修饰的,它的值是不可改变的,这导致每次对String字符串进行操作,都会生成新的String对象,然后再将指针指向新的String对象,这样不仅导致效率低下,还会浪费内存空间。

我们来看下String的部分源码:

/*
被final修饰的类不可被继承
被final修饰的方法不可被重写
被final修饰的变量不可变
*/
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
   
    /** The value is used for character storage.
		该值用于字符存储*/
    private final char value[];

    /** Cache the hash code for the string 
    	缓存字符串的哈希代码*/
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability 
    	使用JDK1.0.2中的serialVersionUID实现互操作性
    */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *类字符串在序列化流协议中是特殊大小写的。
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     字符串实例根据<A href=“{@docRoot}/./platform/serialization/spec写入ObjectOutputStream/output.html“>对象序列化规范,第6.2节,“流元素”</a>     
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];
    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     初始化新创建的{@code String}对象,使其表示空字符序列。请注意,由于字符串是不可变的,因此不需要使用此构造函数。
     */
    public String() {
   
        this.value = "".value;
    }
    .....
}

我们先来看一段简单的代码:

		String str = "gok";
		System.out.println(str);  //gok
		str = str + "666";
		System.out.println(str);  //gok666

在JVM运行时,先创建个str赋值为"gok",在第三行中JVM创建个名也为str的对象,再把666和原来字符串连接的的值赋值给新的str对象,而原来的str会被gc回收机制回收,所以str的值并没有被更改。

在这里插入图片描述

我们能看到,str初始值为"gok",然后在字符串后面加上新的字符串,这个过程需要重新在内存中开辟空间,最终得到"gok666"这个字符串,小小的一个操作需要开辟三个空间,造成了大量地内存浪费执行效率低下

引入StringBuffer和StringBuilder

当要对字符串进行频繁修改时,需要使用StringBuffer和StringBuilder类,来提高效率。与String类不同的是,StringBufferStringBuilder可以对字符串进行多次修改,并且不会产生未使用对象

三者继承结构

在这里插入图片描述

StringBuffer和StringBuilder的区别

StringBuffer和StringBuilder中的方法和功能是完全等价的,都继承AbstractStringBuilder类

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

StringBuffer的大部分方法都被synchronized关键字修饰,线程比较安全,而StringBuilder没有,可以被认为线程不安全

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

在单线程的程序下,StringBuilder效率较高,而StringBuffer每次都要加锁,效率相对较低

String、StringBuffer、StringBuilder效率的比较

	@Test
	public void testStr4() {
   
		// String
		long startString = System.nanoTime();
		String str1 = new String();
		for (int i = 0; i < 10000; i++) {
   
			str1 += "666";
		}
		long endString = System.nanoTime();
		System.out.println("String时间:" + (endString - startString)+
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值