分享

String、StringBuffer、StringBuilder源码解析

 印度阿三17 2019-08-17

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();
        }
    }
}
来源:https://www./content-1-395551.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多