String、StringBuffer、StringBuilder源码解析

String,StringBuffer与 StringBuilder的区别?

String类:

  1. 引用型数据类型
  2. 存储在常量池中

StringBuilder类:

  1. 线程不安全,适合单线程中使用
  2. 具有数据缓存区
  3. 实现了java.io.Serializable接口,可序列化

StringBuffer类:

  1. 线程安全,适合多线程中使用
  2. 具有数据缓存区
  3. 实现了java.io.Serializable接口,可序列化
/*
    final修饰,不能被继承,不可修改
    
    java.io.Serializable:序列化接口仅用于标识序列化。
    					  序列化:对象转换成字节流的一个过程,用来处理对象流的机制。
    					  
    Comparable<String>:接口用于对两个实例化对象比较大小。
    
    CharSequence:只读的字符序列;
    			抽象方法length(), charAt(int index), subSequence(int start, int end)
    			public String toString();
*/

public final class String 
implements java.io.Serializable, Comparable<String>, CharSequence {

	public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            hash = h = isLatin1() ? StringLatin1.hashCode(value)
                                  : StringUTF16.hashCode(value);
        }
        return h;
    }
    
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }
}


final class StringLatin1 {
    public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            for (int i = 0; i < value.length; i++) {
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    
    public static int hashCode(byte[] value) {
        int h = 0;
        int length = value.length >> 1;
        for (int i = 0; i < length; i++) {
            h = 31 * h + getChar(value, i);
        }
        return h;
    }
}

	
final class StringUTF16 {
    public static int hashCode(byte[] value) {
        int h = 0;
        int length = value.length >> 1;
        for (int i = 0; i < length; i++) {
            h = 31 * h + getChar(value, i);
        }
        return h;
    }
    
    @HotSpotIntrinsicCandidate
    public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            int len = value.length >> 1;
            for (int i = 0; i < len; i++) {
                if (getChar(value, i) != getChar(other, i)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}

StringBuilder类源码

特点:

  1. 线程不安全,适合单线程中使用
  2. 具有数据缓存区
  3. 实现了java.io.Serializable接口,可序列化
public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
    static final long serialVersionUID = 4383685877147921099L;
    
    @HotSpotIntrinsicCandidate
    public StringBuilder() {
        super(16);
    }
    
    @HotSpotIntrinsicCandidate
    public StringBuilder(int capacity) {
        super(capacity);
    }
    
    @HotSpotIntrinsicCandidate
    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }
    
    public StringBuilder(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }
    
    
    //个append 方法
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
    public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;
    }
}

//抽线类,这个抽象类值得好好看看
abstract class AbstractStringBuilder implements Appendable, CharSequence {

    byte[] value;//The value is used for character storage.
    
    byte coder;//The id of the encoding used to encode the bytes in {@code value}.
	
    int count;//The count is the number of characters used.

	
	public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }
    
    private AbstractStringBuilder appendNull() {
        ensureCapacityInternal(count + 4);
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            val[count++] = 'n';
            val[count++] = 'u';
            val[count++] = 'l';
            val[count++] = 'l';
        } else {
            count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
        }
        this.count = count;
        return this;
    }
    
    private void ensureCapacityInternal(int minimumCapacity) {
		//移位运算符;<<(左移)、>>(带符号右移)、>>>(无符号右移)
        int oldCapacity = value.length >> coder;
        if (minimumCapacity - oldCapacity > 0) {
        value = Arrays.copyOf(value,newCapacity(minimumCapacity) << coder);
        }
    }
    
   private int newCapacity(int minCapacity) {
        int oldCapacity = value.length >> coder;
        int newCapacity = (oldCapacity << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
            ? hugeCapacity(minCapacity): newCapacity;
    }
    
    private final void putStringAt(int index, String str) {
        if (getCoder() != str.coder()) {
            inflate();
        }
        str.getBytes(value, index, coder);
    }
}

StringBuffer类

特点:

  1. 线程安全,适合多线程中使用
  2. 具有数据缓存区
  3. 实现了java.io.Serializable接口,可序列化

transient:不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
	private transient String toStringCache;
	@Override
    public synchronized int length() {
        return count;
    }

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


    @Override
    public synchronized void ensureCapacity(int minimumCapacity) {
        super.ensureCapacity(minimumCapacity);
    }
    
       @Override
    public synchronized StringBuffer append(Object obj) {
        toStringCache = null;
        super.append(String.valueOf(obj));
        return this;
    }

    @Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    
	@Override
    @HotSpotIntrinsicCandidate
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

}

源码查看
一个小的面试题
测试代码

import org.junit.Test;
import java.util.concurrent.CountDownLatch;

public class StringDiff {
    @Test
    public void testStr() {
        String str = "Hello";

        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
            str+="1";
            //str=str.concat("1");
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);

    }

    /* 被synchronized修饰*/
    @Test
    //线程安全
    public void testStrBuilder() {
        StringBuilder str = new StringBuilder("Hello");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            str.append("BoGe");
        }
        long end = System.currentTimeMillis();
        System.out.println("StringBuilder测试:"+(end - start));
    }

    @Test
    //线程不安全
    public void testStrBuffer() {
        StringBuffer str = new StringBuffer("Hello");

        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            str.append("BoGe");
        }
        long end =System.currentTimeMillis();
        System.out.println("StringBuffer测试:"+(end-start));
    }

    /**CountDownLatch原理:
     *  CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。
     *  当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。
     */

    @SuppressWarnings("all")
    @Test
    public void testStringBuilderAndStringBuffer() {

        CountDownLatch latch1 = new CountDownLatch(1000);
        CountDownLatch latch2 = new CountDownLatch(1000);
        StringBuffer stringBuffer = new StringBuffer();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<1000;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        stringBuilder.append(1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch1.countDown();
                    }
                }
            }).start();
        }
        for(int i=0;i<1000;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        stringBuffer.append(1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        // 递减计数器的计数,如果计数到达零,则释放所有等待的线程。
                        latch2.countDown();
                    }
                }
            }).start();
        }
        
        try {
            latch1.await();
            System.out.println(stringBuilder.length());
            latch2.await();
            System.out.println(stringBuffer.length());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值