【一】String 的特點是什麼?它有哪些重要的方法?

Spring 源碼

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package java.lang;

import java.io.ObjectStreamField;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.StringCoding.Result;
import java.lang.StringLatin1.CharsSpliterator;
import java.lang.StringUTF16.CodePointsSpliterator;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Iterator;
import java.util.Locale;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.Spliterator.OfInt;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.vm.annotation.Stable;

public final class String implements Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
    private final byte coder;
    private int hash;
    private static final long serialVersionUID = -6849794470754667710L;
    static final boolean COMPACT_STRINGS = true;
    private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
    public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator();
    static final byte LATIN1 = 0;
    static final byte UTF16 = 1;

    public String() {
        this.value = "".value;
        this.coder = "".coder;
    }

    @HotSpotIntrinsicCandidate
    public String(String original) {
        this.value = original.value;
        this.coder = original.coder;
        this.hash = original.hash;
    }

    public String(char[] value) {
        this((char[])value, 0, value.length, (Void)null);
    }

    public String(char[] value, int offset, int count) {
        this(value, offset, count, rangeCheck(value, offset, count));
    }

    private static Void rangeCheck(char[] value, int offset, int count) {
        checkBoundsOffCount(offset, count, value.length);
        return null;
    }

    public String(int[] codePoints, int offset, int count) {
        checkBoundsOffCount(offset, count, codePoints.length);
        if (count == 0) {
            this.value = "".value;
            this.coder = "".coder;
        } else {
            if (COMPACT_STRINGS) {
                byte[] val = StringLatin1.toBytes(codePoints, offset, count);
                if (val != null) {
                    this.coder = 0;
                    this.value = val;
                    return;
                }
            }

            this.coder = 1;
            this.value = StringUTF16.toBytes(codePoints, offset, count);
        }
    }

    /** @deprecated */
    @Deprecated(
        since = "1.1"
    )
    public String(byte[] ascii, int hibyte, int offset, int count) {
        checkBoundsOffCount(offset, count, ascii.length);
        if (count == 0) {
            this.value = "".value;
            this.coder = "".coder;
        } else {
            if (COMPACT_STRINGS && (byte)hibyte == 0) {
                this.value = Arrays.copyOfRange(ascii, offset, offset + count);
                this.coder = 0;
            } else {
                hibyte <<= 8;
                byte[] val = StringUTF16.newBytesFor(count);

                for(int i = 0; i < count; ++i) {
                    StringUTF16.putChar(val, i, hibyte | ascii[offset++] & 255);
                }

                this.value = val;
                this.coder = 1;
            }

        }
    }

    /** @deprecated */
    @Deprecated(
        since = "1.1"
    )
    public String(byte[] ascii, int hibyte) {
        this(ascii, hibyte, 0, ascii.length);
    }

    public String(byte[] bytes, int offset, int length, String charsetName) throws UnsupportedEncodingException {
        if (charsetName == null) {
            throw new NullPointerException("charsetName");
        } else {
            checkBoundsOffCount(offset, length, bytes.length);
            Result ret = StringCoding.decode(charsetName, bytes, offset, length);
            this.value = ret.value;
            this.coder = ret.coder;
        }
    }

    public String(byte[] bytes, int offset, int length, Charset charset) {
        if (charset == null) {
            throw new NullPointerException("charset");
        } else {
            checkBoundsOffCount(offset, length, bytes.length);
            Result ret = StringCoding.decode(charset, bytes, offset, length);
            this.value = ret.value;
            this.coder = ret.coder;
        }
    }

    public String(byte[] bytes, String charsetName) throws UnsupportedEncodingException {
        this((byte[])bytes, 0, bytes.length, (String)charsetName);
    }

    public String(byte[] bytes, Charset charset) {
        this((byte[])bytes, 0, bytes.length, (Charset)charset);
    }

    public String(byte[] bytes, int offset, int length) {
        checkBoundsOffCount(offset, length, bytes.length);
        Result ret = StringCoding.decode(bytes, offset, length);
        this.value = ret.value;
        this.coder = ret.coder;
    }

    public String(byte[] bytes) {
        this((byte[])bytes, 0, bytes.length);
    }

    public String(StringBuffer buffer) {
        this(buffer.toString());
    }

    public String(StringBuilder builder) {
        this((AbstractStringBuilder)builder, (Void)null);
    }

    public int length() {
        return this.value.length >> this.coder();
    }

    public boolean isEmpty() {
        return this.value.length == 0;
    }

    public char charAt(int index) {
        return this.isLatin1() ? StringLatin1.charAt(this.value, index) : StringUTF16.charAt(this.value, index);
    }

    public int codePointAt(int index) {
        if (this.isLatin1()) {
            checkIndex(index, this.value.length);
            return this.value[index] & 255;
        } else {
            int length = this.value.length >> 1;
            checkIndex(index, length);
            return StringUTF16.codePointAt(this.value, index, length);
        }
    }

    public int codePointBefore(int index) {
        int i = index - 1;
        if (i >= 0 && i < this.length()) {
            return this.isLatin1() ? this.value[i] & 255 : StringUTF16.codePointBefore(this.value, index);
        } else {
            throw new StringIndexOutOfBoundsException(index);
        }
    }

    public int codePointCount(int beginIndex, int endIndex) {
        if (beginIndex >= 0 && beginIndex <= endIndex && endIndex <= this.length()) {
            return this.isLatin1() ? endIndex - beginIndex : StringUTF16.codePointCount(this.value, beginIndex, endIndex);
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

    public int offsetByCodePoints(int index, int codePointOffset) {
        if (index >= 0 && index <= this.length()) {
            return Character.offsetByCodePoints(this, index, codePointOffset);
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

    public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
        checkBoundsBeginEnd(srcBegin, srcEnd, this.length());
        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
        if (this.isLatin1()) {
            StringLatin1.getChars(this.value, srcBegin, srcEnd, dst, dstBegin);
        } else {
            StringUTF16.getChars(this.value, srcBegin, srcEnd, dst, dstBegin);
        }

    }

    /** @deprecated */
    @Deprecated(
        since = "1.1"
    )
    public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) {
        checkBoundsBeginEnd(srcBegin, srcEnd, this.length());
        Objects.requireNonNull(dst);
        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
        if (this.isLatin1()) {
            StringLatin1.getBytes(this.value, srcBegin, srcEnd, dst, dstBegin);
        } else {
            StringUTF16.getBytes(this.value, srcBegin, srcEnd, dst, dstBegin);
        }

    }

    public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
        if (charsetName == null) {
            throw new NullPointerException();
        } else {
            return StringCoding.encode(charsetName, this.coder(), this.value);
        }
    }

    public byte[] getBytes(Charset charset) {
        if (charset == null) {
            throw new NullPointerException();
        } else {
            return StringCoding.encode(charset, this.coder(), this.value);
        }
    }

    public byte[] getBytes() {
        return StringCoding.encode(this.coder(), this.value);
    }

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        } else {
            if (anObject instanceof String) {
                String aString = (String)anObject;
                if (this.coder() == aString.coder()) {
                    return this.isLatin1() ? StringLatin1.equals(this.value, aString.value) : StringUTF16.equals(this.value, aString.value);
                }
            }

            return false;
        }
    }

    public boolean contentEquals(StringBuffer sb) {
        return this.contentEquals((CharSequence)sb);
    }

    private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
        int len = this.length();
        if (len != sb.length()) {
            return false;
        } else {
            byte[] v1 = this.value;
            byte[] v2 = sb.getValue();
            if (this.coder() == sb.getCoder()) {
                int n = v1.length;

                for(int i = 0; i < n; ++i) {
                    if (v1[i] != v2[i]) {
                        return false;
                    }
                }

                return true;
            } else {
                return !this.isLatin1() ? false : StringUTF16.contentEquals(v1, v2, len);
            }
        }
    }

    public boolean contentEquals(CharSequence cs) {
        if (cs instanceof AbstractStringBuilder) {
            if (cs instanceof StringBuffer) {
                synchronized(cs) {
                    return this.nonSyncContentEquals((AbstractStringBuilder)cs);
                }
            } else {
                return this.nonSyncContentEquals((AbstractStringBuilder)cs);
            }
        } else if (cs instanceof String) {
            return this.equals(cs);
        } else {
            int n = cs.length();
            if (n != this.length()) {
                return false;
            } else {
                byte[] val = this.value;
                if (this.isLatin1()) {
                    for(int i = 0; i < n; ++i) {
                        if ((val[i] & 255) != cs.charAt(i)) {
                            return false;
                        }
                    }
                } else if (!StringUTF16.contentEquals(val, cs, n)) {
                    return false;
                }

                return true;
            }
        }
    }

    public boolean equalsIgnoreCase(String anotherString) {
        return this == anotherString ? true : anotherString != null && anotherString.length() == this.length() && this.regionMatches(true, 0, anotherString, 0, this.length());
    }

    public int compareTo(String anotherString) {
        byte[] v1 = this.value;
        byte[] v2 = anotherString.value;
        if (this.coder() == anotherString.coder()) {
            return this.isLatin1() ? StringLatin1.compareTo(v1, v2) : StringUTF16.compareTo(v1, v2);
        } else {
            return this.isLatin1() ? StringLatin1.compareToUTF16(v1, v2) : StringUTF16.compareToLatin1(v1, v2);
        }
    }

    public int compareToIgnoreCase(String str) {
        return CASE_INSENSITIVE_ORDER.compare(this, str);
    }

    public boolean regionMatches(int toffset, String other, int ooffset, int len) {
        byte[] tv = this.value;
        byte[] ov = other.value;
        if (ooffset >= 0 && toffset >= 0 && (long)toffset <= (long)this.length() - (long)len && (long)ooffset <= (long)other.length() - (long)len) {
            if (this.coder() == other.coder()) {
                if (!this.isLatin1() && len > 0) {
                    toffset <<= 1;
                    ooffset <<= 1;
                    len <<= 1;
                }

                while(len-- > 0) {
                    if (tv[toffset++] != ov[ooffset++]) {
                        return false;
                    }
                }
            } else if (this.coder() == 0) {
                while(len-- > 0) {
                    if (StringLatin1.getChar(tv, toffset++) != StringUTF16.getChar(ov, ooffset++)) {
                        return false;
                    }
                }
            } else {
                while(len-- > 0) {
                    if (StringUTF16.getChar(tv, toffset++) != StringLatin1.getChar(ov, ooffset++)) {
                        return false;
                    }
                }
            }

            return true;
        } else {
            return false;
        }
    }

    public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
        if (!ignoreCase) {
            return this.regionMatches(toffset, other, ooffset, len);
        } else if (ooffset >= 0 && toffset >= 0 && (long)toffset <= (long)this.length() - (long)len && (long)ooffset <= (long)other.length() - (long)len) {
            byte[] tv = this.value;
            byte[] ov = other.value;
            if (this.coder() == other.coder()) {
                return this.isLatin1() ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
            } else {
                return this.isLatin1() ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
            }
        } else {
            return false;
        }
    }

    public boolean startsWith(String prefix, int toffset) {
        if (toffset >= 0 && toffset <= this.length() - prefix.length()) {
            byte[] ta = this.value;
            byte[] pa = prefix.value;
            int po = 0;
            int pc = pa.length;
            if (this.coder() == prefix.coder()) {
                int var7 = this.isLatin1() ? toffset : toffset << 1;

                while(po < pc) {
                    if (ta[var7++] != pa[po++]) {
                        return false;
                    }
                }
            } else {
                if (this.isLatin1()) {
                    return false;
                }

                while(po < pc) {
                    if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 255)) {
                        return false;
                    }
                }
            }

            return true;
        } else {
            return false;
        }
    }

    public boolean startsWith(String prefix) {
        return this.startsWith(prefix, 0);
    }

    public boolean endsWith(String suffix) {
        return this.startsWith(suffix, this.length() - suffix.length());
    }

    public int hashCode() {
        int h = this.hash;
        if (h == 0 && this.value.length > 0) {
            this.hash = h = this.isLatin1() ? StringLatin1.hashCode(this.value) : StringUTF16.hashCode(this.value);
        }

        return h;
    }

    public int indexOf(int ch) {
        return this.indexOf(ch, 0);
    }

    public int indexOf(int ch, int fromIndex) {
        return this.isLatin1() ? StringLatin1.indexOf(this.value, ch, fromIndex) : StringUTF16.indexOf(this.value, ch, fromIndex);
    }

    public int lastIndexOf(int ch) {
        return this.lastIndexOf(ch, this.length() - 1);
    }

    public int lastIndexOf(int ch, int fromIndex) {
        return this.isLatin1() ? StringLatin1.lastIndexOf(this.value, ch, fromIndex) : StringUTF16.lastIndexOf(this.value, ch, fromIndex);
    }

    public int indexOf(String str) {
        if (this.coder() == str.coder()) {
            return this.isLatin1() ? StringLatin1.indexOf(this.value, str.value) : StringUTF16.indexOf(this.value, str.value);
        } else {
            return this.coder() == 0 ? -1 : StringUTF16.indexOfLatin1(this.value, str.value);
        }
    }

    public int indexOf(String str, int fromIndex) {
        return indexOf(this.value, this.coder(), this.length(), str, fromIndex);
    }

    static int indexOf(byte[] src, byte srcCoder, int srcCount, String tgtStr, int fromIndex) {
        byte[] tgt = tgtStr.value;
        byte tgtCoder = tgtStr.coder();
        int tgtCount = tgtStr.length();
        if (fromIndex >= srcCount) {
            return tgtCount == 0 ? srcCount : -1;
        } else {
            if (fromIndex < 0) {
                fromIndex = 0;
            }

            if (tgtCount == 0) {
                return fromIndex;
            } else if (tgtCount > srcCount) {
                return -1;
            } else if (srcCoder == tgtCoder) {
                return srcCoder == 0 ? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex) : StringUTF16.indexOf(src, srcCount, tgt, tgtCount, fromIndex);
            } else {
                return srcCoder == 0 ? -1 : StringUTF16.indexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
            }
        }
    }

    public int lastIndexOf(String str) {
        return this.lastIndexOf(str, this.length());
    }

    public int lastIndexOf(String str, int fromIndex) {
        return lastIndexOf(this.value, this.coder(), this.length(), str, fromIndex);
    }

    static int lastIndexOf(byte[] src, byte srcCoder, int srcCount, String tgtStr, int fromIndex) {
        byte[] tgt = tgtStr.value;
        byte tgtCoder = tgtStr.coder();
        int tgtCount = tgtStr.length();
        int rightIndex = srcCount - tgtCount;
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }

        if (fromIndex < 0) {
            return -1;
        } else if (tgtCount == 0) {
            return fromIndex;
        } else if (srcCoder == tgtCoder) {
            return srcCoder == 0 ? StringLatin1.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex) : StringUTF16.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex);
        } else {
            return srcCoder == 0 ? -1 : StringUTF16.lastIndexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
        }
    }

    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        } else {
            int subLen = this.length() - beginIndex;
            if (subLen < 0) {
                throw new StringIndexOutOfBoundsException(subLen);
            } else if (beginIndex == 0) {
                return this;
            } else {
                return this.isLatin1() ? StringLatin1.newString(this.value, beginIndex, subLen) : StringUTF16.newString(this.value, beginIndex, subLen);
            }
        }
    }

    public String substring(int beginIndex, int endIndex) {
        int length = this.length();
        checkBoundsBeginEnd(beginIndex, endIndex, length);
        int subLen = endIndex - beginIndex;
        if (beginIndex == 0 && endIndex == length) {
            return this;
        } else {
            return this.isLatin1() ? StringLatin1.newString(this.value, beginIndex, subLen) : StringUTF16.newString(this.value, beginIndex, subLen);
        }
    }

    public CharSequence subSequence(int beginIndex, int endIndex) {
        return this.substring(beginIndex, endIndex);
    }

    public String concat(String str) {
        int olen = str.length();
        if (olen == 0) {
            return this;
        } else {
            byte[] buf;
            if (this.coder() == str.coder()) {
                byte[] val = this.value;
                buf = str.value;
                int len = val.length + buf.length;
                byte[] buf = Arrays.copyOf(val, len);
                System.arraycopy(buf, 0, buf, val.length, buf.length);
                return new String(buf, this.coder);
            } else {
                int len = this.length();
                buf = StringUTF16.newBytesFor(len + olen);
                this.getBytes(buf, 0, (byte)1);
                str.getBytes(buf, len, (byte)1);
                return new String(buf, (byte)1);
            }
        }
    }

    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            String ret = this.isLatin1() ? StringLatin1.replace(this.value, oldChar, newChar) : StringUTF16.replace(this.value, oldChar, newChar);
            if (ret != null) {
                return ret;
            }
        }

        return this;
    }

    public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }

    public boolean contains(CharSequence s) {
        return this.indexOf(s.toString()) >= 0;
    }

    public String replaceFirst(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
    }

    public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

    public String replace(CharSequence target, CharSequence replacement) {
        String tgtStr = target.toString();
        String replStr = replacement.toString();
        int j = this.indexOf(tgtStr);
        if (j < 0) {
            return this;
        } else {
            int tgtLen = tgtStr.length();
            int tgtLen1 = Math.max(tgtLen, 1);
            int thisLen = this.length();
            int newLenHint = thisLen - tgtLen + replStr.length();
            if (newLenHint < 0) {
                throw new OutOfMemoryError();
            } else {
                StringBuilder sb = new StringBuilder(newLenHint);
                int i = 0;

                do {
                    sb.append(this, i, j).append(replStr);
                    i = j + tgtLen;
                } while(j < thisLen && (j = this.indexOf(tgtStr, j + tgtLen1)) > 0);

                return sb.append(this, i, thisLen).toString();
            }
        }
    }

    public String[] split(String regex, int limit) {
        char ch = 0;
        if ((regex.length() != 1 || ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) != -1) && (regex.length() != 2 || regex.charAt(0) != '\\' || ((ch = regex.charAt(1)) - 48 | 57 - ch) >= 0 || (ch - 97 | 122 - ch) >= 0 || (ch - 65 | 90 - ch) >= 0) || ch >= '\ud800' && ch <= '\udfff') {
            return Pattern.compile(regex).split(this, limit);
        } else {
            int off = 0;
            int next = false;
            boolean limited = limit > 0;

            ArrayList list;
            int resultSize;
            int next;
            for(list = new ArrayList(); (next = this.indexOf(ch, off)) != -1; off = next + 1) {
                if (limited && list.size() >= limit - 1) {
                    resultSize = this.length();
                    list.add(this.substring(off, resultSize));
                    off = resultSize;
                    break;
                }

                list.add(this.substring(off, next));
            }

            if (off == 0) {
                return new String[]{this};
            } else {
                if (!limited || list.size() < limit) {
                    list.add(this.substring(off, this.length()));
                }

                resultSize = list.size();
                if (limit == 0) {
                    while(resultSize > 0 && ((String)list.get(resultSize - 1)).length() == 0) {
                        --resultSize;
                    }
                }

                String[] result = new String[resultSize];
                return (String[])list.subList(0, resultSize).toArray(result);
            }
        }
    }

    public String[] split(String regex) {
        return this.split(regex, 0);
    }

    public static String join(CharSequence delimiter, CharSequence... elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        StringJoiner joiner = new StringJoiner(delimiter);
        CharSequence[] var3 = elements;
        int var4 = elements.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            CharSequence cs = var3[var5];
            joiner.add(cs);
        }

        return joiner.toString();
    }

    public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        StringJoiner joiner = new StringJoiner(delimiter);
        Iterator var3 = elements.iterator();

        while(var3.hasNext()) {
            CharSequence cs = (CharSequence)var3.next();
            joiner.add(cs);
        }

        return joiner.toString();
    }

    public String toLowerCase(Locale locale) {
        return this.isLatin1() ? StringLatin1.toLowerCase(this, this.value, locale) : StringUTF16.toLowerCase(this, this.value, locale);
    }

    public String toLowerCase() {
        return this.toLowerCase(Locale.getDefault());
    }

    public String toUpperCase(Locale locale) {
        return this.isLatin1() ? StringLatin1.toUpperCase(this, this.value, locale) : StringUTF16.toUpperCase(this, this.value, locale);
    }

    public String toUpperCase() {
        return this.toUpperCase(Locale.getDefault());
    }

    public String trim() {
        String ret = this.isLatin1() ? StringLatin1.trim(this.value) : StringUTF16.trim(this.value);
        return ret == null ? this : ret;
    }

    public String strip() {
        String ret = this.isLatin1() ? StringLatin1.strip(this.value) : StringUTF16.strip(this.value);
        return ret == null ? this : ret;
    }

    public String stripLeading() {
        String ret = this.isLatin1() ? StringLatin1.stripLeading(this.value) : StringUTF16.stripLeading(this.value);
        return ret == null ? this : ret;
    }

    public String stripTrailing() {
        String ret = this.isLatin1() ? StringLatin1.stripTrailing(this.value) : StringUTF16.stripTrailing(this.value);
        return ret == null ? this : ret;
    }

    public boolean isBlank() {
        return this.indexOfNonWhitespace() == this.length();
    }

    private int indexOfNonWhitespace() {
        return this.isLatin1() ? StringLatin1.indexOfNonWhitespace(this.value) : StringUTF16.indexOfNonWhitespace(this.value);
    }

    public Stream<String> lines() {
        return this.isLatin1() ? StringLatin1.lines(this.value) : StringUTF16.lines(this.value);
    }

    public String toString() {
        return this;
    }

    public IntStream chars() {
        return StreamSupport.intStream((OfInt)(this.isLatin1() ? new CharsSpliterator(this.value, 1024) : new java.lang.StringUTF16.CharsSpliterator(this.value, 1024)), false);
    }

    public IntStream codePoints() {
        return StreamSupport.intStream((OfInt)(this.isLatin1() ? new CharsSpliterator(this.value, 1024) : new CodePointsSpliterator(this.value, 1024)), false);
    }

    public char[] toCharArray() {
        return this.isLatin1() ? StringLatin1.toChars(this.value) : StringUTF16.toChars(this.value);
    }

    public static String format(String format, Object... args) {
        return (new Formatter()).format(format, args).toString();
    }

    public static String format(Locale l, String format, Object... args) {
        return (new Formatter(l)).format(format, args).toString();
    }

    public static String valueOf(Object obj) {
        return obj == null ? "null" : obj.toString();
    }

    public static String valueOf(char[] data) {
        return new String(data);
    }

    public static String valueOf(char[] data, int offset, int count) {
        return new String(data, offset, count);
    }

    public static String copyValueOf(char[] data, int offset, int count) {
        return new String(data, offset, count);
    }

    public static String copyValueOf(char[] data) {
        return new String(data);
    }

    public static String valueOf(boolean b) {
        return b ? "true" : "false";
    }

    public static String valueOf(char c) {
        return COMPACT_STRINGS && StringLatin1.canEncode(c) ? new String(StringLatin1.toBytes(c), (byte)0) : new String(StringUTF16.toBytes(c), (byte)1);
    }

    public static String valueOf(int i) {
        return Integer.toString(i);
    }

    public static String valueOf(long l) {
        return Long.toString(l);
    }

    public static String valueOf(float f) {
        return Float.toString(f);
    }

    public static String valueOf(double d) {
        return Double.toString(d);
    }

    public native String intern();

    public String repeat(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count is negative: " + count);
        } else if (count == 1) {
            return this;
        } else {
            int len = this.value.length;
            if (len != 0 && count != 0) {
                if (len == 1) {
                    byte[] single = new byte[count];
                    Arrays.fill(single, this.value[0]);
                    return new String(single, this.coder);
                } else if (2147483647 / count < len) {
                    throw new OutOfMemoryError("Repeating " + len + " bytes String " + count + " times will produce a String exceeding maximum size.");
                } else {
                    int limit = len * count;
                    byte[] multiple = new byte[limit];
                    System.arraycopy(this.value, 0, multiple, 0, len);

                    int copied;
                    for(copied = len; copied < limit - copied; copied <<= 1) {
                        System.arraycopy(multiple, 0, multiple, copied, copied);
                    }

                    System.arraycopy(multiple, 0, multiple, copied, limit - copied);
                    return new String(multiple, this.coder);
                }
            } else {
                return "";
            }
        }
    }

    void getBytes(byte[] dst, int dstBegin, byte coder) {
        if (this.coder() == coder) {
            System.arraycopy(this.value, 0, dst, dstBegin << coder, this.value.length);
        } else {
            StringLatin1.inflate(this.value, 0, dst, dstBegin, this.value.length);
        }

    }

    String(char[] value, int off, int len, Void sig) {
        if (len == 0) {
            this.value = "".value;
            this.coder = "".coder;
        } else {
            if (COMPACT_STRINGS) {
                byte[] val = StringUTF16.compress(value, off, len);
                if (val != null) {
                    this.value = val;
                    this.coder = 0;
                    return;
                }
            }

            this.coder = 1;
            this.value = StringUTF16.toBytes(value, off, len);
        }
    }

    String(AbstractStringBuilder asb, Void sig) {
        byte[] val = asb.getValue();
        int length = asb.length();
        if (asb.isLatin1()) {
            this.coder = 0;
            this.value = Arrays.copyOfRange(val, 0, length);
        } else {
            if (COMPACT_STRINGS) {
                byte[] buf = StringUTF16.compress(val, 0, length);
                if (buf != null) {
                    this.coder = 0;
                    this.value = buf;
                    return;
                }
            }

            this.coder = 1;
            this.value = Arrays.copyOfRange(val, 0, length << 1);
        }

    }

    String(byte[] value, byte coder) {
        this.value = value;
        this.coder = coder;
    }

    byte coder() {
        return COMPACT_STRINGS ? this.coder : 1;
    }

    byte[] value() {
        return this.value;
    }

    private boolean isLatin1() {
        return COMPACT_STRINGS && this.coder == 0;
    }

    static void checkIndex(int index, int length) {
        if (index < 0 || index >= length) {
            throw new StringIndexOutOfBoundsException("index " + index + ",length " + length);
        }
    }

    static void checkOffset(int offset, int length) {
        if (offset < 0 || offset > length) {
            throw new StringIndexOutOfBoundsException("offset " + offset + ",length " + length);
        }
    }

    static void checkBoundsOffCount(int offset, int count, int length) {
        if (offset < 0 || count < 0 || offset > length - count) {
            throw new StringIndexOutOfBoundsException("offset " + offset + ", count " + count + ", length " + length);
        }
    }

    static void checkBoundsBeginEnd(int begin, int end, int length) {
        if (begin < 0 || begin > end || end > length) {
            throw new StringIndexOutOfBoundsException("begin " + begin + ", end " + end + ", length " + length);
        }
    }

    static String valueOfCodePoint(int codePoint) {
        if (COMPACT_STRINGS && StringLatin1.canEncode(codePoint)) {
            return new String(StringLatin1.toBytes((char)codePoint), (byte)0);
        } else if (Character.isBmpCodePoint(codePoint)) {
            return new String(StringUTF16.toBytes((char)codePoint), (byte)1);
        } else if (Character.isSupplementaryCodePoint(codePoint)) {
            return new String(StringUTF16.toBytesSupplementary(codePoint), (byte)1);
        } else {
            throw new IllegalArgumentException(format("Not a valid Unicode code point: 0x%X", codePoint));
        }
    }

    private static class CaseInsensitiveComparator implements Comparator<String>, Serializable {
        private static final long serialVersionUID = 8575799808933029326L;

        private CaseInsensitiveComparator() {
        }

        public int compare(String s1, String s2) {
            byte[] v1 = s1.value;
            byte[] v2 = s2.value;
            if (s1.coder() == s2.coder()) {
                return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) : StringUTF16.compareToCI(v1, v2);
            } else {
                return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2) : StringUTF16.compareToCI_Latin1(v1, v2);
            }
        }

        private Object readResolve() {
            return String.CASE_INSENSITIVE_ORDER;
        }
    }
}

多構造方法

String 字符串有以下 4 個重要的構造方法

// String 爲參數的構造方法
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
// char[] 爲參數構造方法
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
// StringBuffer 爲參數的構造方法
public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}
// StringBuilder 爲參數的構造方法
public String(StringBuilder builder) {
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

其中,比較容易被我們忽略的是以 StringBuffer 和 StringBuilder 爲參數的構造函數,因爲這三種數據類型,我們通常都是單獨使用的,所以這個小細節我們需要特別留意一下。

equals() 比較兩個字符串是否相等

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        } else {
            if (anObject instanceof String) {
                String aString = (String)anObject;
                if (this.coder() == aString.coder()) {
                    return this.isLatin1() ? StringLatin1.equals(this.value, aString.value) : StringUTF16.equals(this.value, aString.value);
                }
            }

            return false;
        }
    }

看着比較難理解,可以理解成下面

public boolean equals(Object anObject) {
    // 對象引用相同直接返回 true
    if (this == anObject) {
        return true;
    }
    // 判斷需要對比的值是否爲 String 類型,如果不是則直接返回 false
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            // 把兩個字符串都轉換爲 char 數組對比
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // 循環比對兩個字符串的每一個字符
            while (n-- != 0) {
                // 如果其中有一個字符不相等就 true false,否則繼續對比
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

String 類型重寫了 Object 中的 equals() 方法,equals() 方法需要傳遞一個 Object 類型的參數值,

1.在比較時會先通過 instanceof 判斷是否爲 String 類型,如果不是則會直接返回 false

2.當判斷參數爲 String 類型之後,會循環對比兩個字符串中的每一個字符,當所有字符都相等時返回 true,否則則返回 false。

還有一個和 equals() 比較類似的方法 equalsIgnoreCase(),它是用於忽略字符串的大小寫之後進行字符串對比。

compareTo() 比較兩個字符串

compareTo() 方法用於比較兩個字符串,返回的結果爲 int 類型的值,源碼如下:

public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;
    // 獲取到兩個字符串長度最短的那個 int 值
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;
    int k = 0;
    // 對比每一個字符
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            // 有字符不相等就返回差值
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章