JAVA中String,StringBuilder,StringBuffer三者的区别原理

三者源码上的区别:

  1. 在java 8 ,也就是jdk1.8中我们可以看到关于String的部分源码
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    }

在源码中我们可以看见用来储存字符串的字符数组被定义成了final常量。

private final char value[];

所以说String是不可变字符串。

  1. 在jdk1.8中关于StringBuilder的部分源码
public final class StringBuilder
   extends AbstractStringBuilder
   implements java.io.Serializable, CharSequence
{

   /** use serialVersionUID for interoperability */
   static final long serialVersionUID = 4383685877147921099L;

   /**
    * Constructs a string builder with no characters in it and an
    * initial capacity of 16 characters.
    */
   public StringBuilder() {
       super(16);
   }
}
  1. jdk1.8中StringBuffer的部分源码
public final class StringBuffer
   extends AbstractStringBuilder
   implements java.io.Serializable, CharSequence
{

   /**
    * A cache of the last value returned by toString. Cleared
    * whenever the StringBuffer is modified.
    */
   private transient char[] toStringCache;

   /** use serialVersionUID from JDK 1.0.2 for interoperability */
   static final long serialVersionUID = 3388685877147921107L;

   /**
    * Constructs a string buffer with no characters in it and an
    * initial capacity of 16 characters.
    */
   public StringBuffer() {
       super(16);
   }
}

4.StringBuilder和StringBuffer都继承AbstractStringBuilder,以下是AbstractStringBuilder的部分源码

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;

    /**
     * The count is the number of characters used.
     */
    int count;

在AbstractStringBuilder的源码中发现,用来存储字符串的字符数组并没有被定义成final常量。
根据char[] value;这行代码,StringBuilder和StringBuffer都是可变字符串。


三者关于线程是否安全的问题:
线程,我们简单理解为每个程序执行的基本单元。
String字符串是常量,它是不可被改变的,所以String线程是安全的。

 private final char value[];

AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity(),append(),insert(),indexOf()等公共方法。
StringBuffer对方法加了同步锁(synchronized)或者对调用的方法加了同步锁(synchronized),所以是线程安全的。

   @Override
    public synchronized String substring(int start, int end) {
        return super.substring(start, end);
    }

    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     * @since      1.2
     */
    @Override
    public synchronized StringBuffer insert(int index, char[] str, int offset,
                                            int len)
    {
        toStringCache = null;
        super.insert(index, str, offset, len);
        return this;
    }

    public int indexOf(String str) {
       return indexOf(str, 0);        //存在 public synchronized int indexOf(String str, int fromIndex) 方法
 }

而在StringBuilder的源码中并没有加同步锁,所以StringBuilder是非线程安全的。


三者的运算速度问题:
StringBuilder > StringBuffer > String
StringBuilder 最快,StringBuffer 第二,String 最慢。
因为String是字符串常量,看如下代码:

String str="abc";
System.out.println(str);
str=str+"de";
System.out.println(str);

我们肉眼来看好像确实str被更改了,但是并不是这样的。
首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。
所以String字符串更改就是重新创建对象,重新赋值,重新创建对象,重新赋值……这样的循环
但是StringBuffer和StringBuilder都是可以更改的。

public static void testStringBuffer(){
        long start = System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0;i<200000;i++){
            stringBuffer.append(i);
        }
        System.out.println(System.currentTimeMillis() - start);
    }
public static void testStringBuilder(){
        long start = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0;i<200000;i++){
            stringBuilder.append(i);
        }
        System.out.println(System.currentTimeMillis() - start);
    }
public static void main(String[] args) {
        // TODO Auto-generated method stub
        testStringBuffer();
        testStringBuilder();
    }

运行结果如下:
在这里插入图片描述


总结:
String:适用于少量的字符串操作的情况

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值