字符串拼接

字符串拼接,之前使用的"字符串"+"字符串"的方式,但是会在字符串常量池中生成大量的字符串对象,因此,在字符串的拼接中,一般使用StringBuffer火StringBuilder。

首先需要了解为啥字符串常量无法更改,通过查看String类源码,会发现如下代码:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

可以看到,字符串是通过一个常量数组存储的,这就是无法更改的原因。那为何StringBuffer就可以取得更好的效果呢?在查看StringBuffer的相关源码后:

/**
     * 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);
    }

    /**
     * Constructs a string buffer with no characters in it and
     * the specified initial capacity.
     *
     * @param      capacity  the initial capacity.
     * @exception  NegativeArraySizeException  if the {@code capacity}
     *               argument is less than {@code 0}.
     */
    public StringBuffer(int capacity) {
        super(capacity);
    }

再次查找其父类:AbstractStringBuilder的相关源码:

/**
     * The value is used for character storage.
     */
    char[] value;

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

    /**
     * This no-arg constructor is necessary for serialization of subclasses.
     */
    AbstractStringBuilder() {
    }

    /**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

会发现有几个不同点,第一,它仍然是通过一个数组进行存储,但是,不是final,而且还提供了一个用来缓存的数组;第二,这个数组有一个长度,初始大小为16;

通过使用append方法拼接字符串,前面也说过,由于数组长度限制了,那拼接时就会超过这个长度,那应该如何解决?

查看append方法源码:

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

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

继续查看其父类:

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

查看ensureCapacityInternal()这个方法:

 private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }

    /**
     * This implements the expansion semantics of ensureCapacity with no
     * size check or synchronization.
     */
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
    }

会发现:

value = Arrays.copyOf(value, newCapacity);也就是说,进行了数组扩容

StringBuffer和StringBuilder都可以用来拼接字符串,区别是,安全性不同,查看源码后会发现StingBuffer的成员方法均含有关键字“synchronized ”,而StringBuilder没有

即StringBuffer时线程安全的

 

posted @ 2020-10-28 09:02  执着的乌龟  阅读(190)  评论(0编辑  收藏  举报