【java基础】-String、StringBuffer、StringBuilder的区别

1.String是不可变类

也就是说,String对象一旦创建,其值将不能被改变,String对象改变实质是new了一个新的String对象。对于String s1="abc"语句与String s2=“abc”语句,在JVM中存在着一个字符串池,其中保存着很多String对象。并且可以被共享使用,s1、s2引用的是同一个常量池中的对象。由于String的实现采用了Flyweight的设计模式,当创建一个字符串常量时,例如String s="abc",会首先在字符串常量池中查找是否已经有相同的字符串被定义,其判断依据是String类equals(Object obj)方法的返回值。若已经定义,则直接获取对其的引用,此时不需要创建新的对象;若没有定义,则首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。由于String是不可变类,一旦创建好了就不能被修改,因此String对象可以被共享而且不会导致程序的混乱。

    	String s1="abc";//在常量区里面存放一个“abc”字符串对象
    	String s2="abc";//s2引用常量区中的对象,因此不会创建新的对象
    	String s3=new String("abc");//在堆中创建新的对象
    	String s4=new String("abc");//在堆中又创建一个新的对象

在执行new String("abc")会调用String类的构造函数:

public String(String orginal){
    //body
}

在调用这个构造函数时,传入了一个字符串常量,因此语句new String("abc")也就等价于“abc”和new String()两个操作了。若在字符串池中不存在“abc”,则会创建一个字符串常量“abc”,并将其添加到字符串池中;若存在,就不创建,然后new String()会在堆中创建一个新的对象,所以s3与s4指向的是堆中不同的String对象,地址自然也就不同了,如图:

思考题:new String("abc");创建了几个对象?

答案:一个或两个

2.线程安全的可变类StringBuffer-字符串缓冲区

当一个字符串经常需要被修改时,最好使用StringBuffer来实现。如果用String来保存一个经常被修改的字符串时,在字符串被修改时会比StringBuffer多很多附加的操作,同时生成许多无用的对象,由于这些无用的对象会被垃圾回收器来回收,因此会影响程序的性能。在规模小的项目里面这个影响很小,但是在一个规模大的项目里面,这会对程序的运行效率带来很大的影响。

String与StringBuffer的另一个区别是在于实例化String时,可以利用构造函数(String s1=new String("world"))的方式来对其进行初始化,也可以用赋值(String s="hello")的方式来初始化,而StringBuffer只能使用构造函(StringBuffer s=new StringBuffer("hello"))的方式来初始化。

StringBuffer继承了抽象类AbstractStringBuilder,在AbstractStringBuilder类中,有两个字段分别是char[]类型的value和int类型的count,也就是说,StringBuffer本质上是一个字符数组:

    /**
     * The value is used for character storage.
     */
    char[] value;
 
    /**
     * The count is the number of characters used.
     */
    int count;

value用来存储字符,而count表示数组中已有内容的大小,也就是长度。StringBuffer的主要操作有append、insert等,这些操作都是在value上进行的,而不是像String一样每次操作都要new一个String,因此,StringBuffer在效率上要高于String。有了append、insert等操作,value的大小就会改变。

3.StringBuilder-线程不安全的字符串缓冲区

StringBuilder也可以被修饰的字符串,它与StringBuffer类似,都是字符串缓冲区,但是StringBuilder不是线程安全的,如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高一些。因此在只有单线程访问时可以使用StringBuilder,当又多个线程访问时,最好使用线程安全的StringBuffer。因为StringBuffer必要时可以对这些方法进行同步,所以任意特定实例上的操作就好像是以串行顺序发生的,该顺序与所设计的每个线程进行的方法调用顺序一致。

4.总结

在执行效率方面,StringBuilder最高,StringBuffer次之,String最低,鉴于这一情况,一般而言,如果要操作的数据量比较小,应优先使用String类;如果在单线程下操作大量数据,应优先使用StringBuilder;如果在多线程下操作大量数据,应优先考虑StringBuffer类。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值