JDK1.8源码学习--lang包(String)

本文详细介绍了Java中的String类,包括其作用、特性、内部结构、方法以及常用操作,如构造、比较、查找、替换、截取等。String是不可变的,它的操作会创建新的对象,同时探讨了其在Unicode编码下的处理。文章还提到了String与其他对象(如StringBuilder、Character)的交互,以及序列化和比较规则。
摘要由CSDN通过智能技术生成

前言

 
月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂)

央是一片海洋,海乃百川,代表着一块海绵(吸纳万物)

泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出)

月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容

希望大家一起坚持这个过程,也同样希望大家最终都能从零到零,把知识从薄变厚,再由厚变薄!
 

一.String的作用:

        直接看源码注释(我的翻译可能不太准,如果道友们有更棒的理解,可以留言或者私信)

/**
 * The {@code String} class represents character strings. All
 * string literals in Java programs, such as {@code "abc"}, are
 * implemented as instances of this class.
 * 1.String类表示字符串。 Java 程序中的所有字符串文字,例如"abc",都是作为此类的实例实现的。
 * <p>
 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared.
 * 2.字符串是常量;它们的值在创建后无法更改。字符串缓冲区支持可变字符串。
 * 因为 String 对象是不可变的,所以它们可以共享
 * 3.例如: String str = "abc";  等价于: char data[] = {'a', 'b', 'c'};
 * String str = new String(data);
 * For example:
 * <blockquote><pre>
 *     String str = "abc";
 * </pre></blockquote><p>
 * is equivalent to:
 * <blockquote><pre>
 *     char data[] = {'a', 'b', 'c'};
 *     String str = new String(data);
 * </pre></blockquote><p>
 * Here are some more examples of how strings can be used:
 * <blockquote><pre>
 *     System.out.println("abc");
 *     String cde = "cde";
 *     System.out.println("abc" + cde);
 *     String c = "abc".substring(2,3);
 *     String d = cde.substring(1, 2);
 * 4.下面是一些如何使用字符串的更多示例:System.out.println("abc");
 * 字符串 cde = "cde";
 * System.out.println("abc" + cde);
 * String c = "abc".substring(2,3);
 * 字符串 d = cde.substring(1, 2);
 * </pre></blockquote>
 * <p>
 * The class {@code String} includes methods for examining
 * individual characters of the sequence, for comparing strings, for
 * searching strings, for extracting substrings, and for creating a
 * copy of a string with all characters translated to uppercase or to
 * lowercase. Case mapping is based on the Unicode Standard version
 * specified by the {@link java.lang.Character Character} class.
 * 5.String类包括用于检查序列中的单个字符、比较字符串、搜索字符串、提取子字符串
 * 以及创建所有字符都转换为大写或小写的字符串副本的方法。大
 * 小写映射基于 java.lang.Character 类指定的 Unicode 标准版本。
 * <p>
 * The Java language provides special support for the string
 * concatenation operator (&nbsp;+&nbsp;), and for conversion of
 * other objects to strings. String concatenation is implemented
 * through the {@code StringBuilder}(or {@code StringBuffer})
 * class and its {@code append} method.
 * 6.Java 语言为字符串连接运算符 (+) 以及将其他对象转换为字符串提供特殊支持。
 * 字符串连接是通过 StringBuilder(或  StringBuffer)类及其  append方法实现的
 * String conversions are implemented through the method
 * {@code toString}, defined by {@code Object} and
 * inherited by all classes in Java. For additional information on
 * string concatenation and conversion, see Gosling, Joy, and Steele,
 * <i>The Java Language Specification</i>.
 * 7.字符串转换通过toString方法实现,由Object定义,Java中所有类都继承。
 * 有关字符串串联和转换的其他信息,请参阅 Gosling、Joy 和 Steele,Java 语言规范。
 * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
 * or method in this class will cause a {@link NullPointerException} to be
 * thrown.
 * 8.除非另有说明,否则将 null参数传递给此类中的构造函数或方法将导致抛出 NullPointerException。
 * <p>A {@code String} represents a string in the UTF-16 format
 * in which <em>supplementary characters</em> are represented by <em>surrogate
 * pairs</em> (see the section <a href="Character.html#unicode">Unicode
 * Character Representations</a> in the {@code Character} class for
 * more information).
 * 9.String表示 UTF-16 格式的字符串,其中补充字符由代理对表示
 * (请参阅<a href="Character.htmlunicode">部分Character类中的 Unicode字符表示了解更多信息)。
 * Index values refer to {@code char} code units, so a supplementary
 * character uses two positions in a {@code String}.
 * <p>The {@code String} class provides methods for dealing with
 * Unicode code points (i.e., characters), in addition to those for
 * dealing with Unicode code units (i.e., {@code char} values).
 * 10.索引值引用char代码单元,因此增补字符使用String中的两个位置。
 * String类提供处理 Unicode 代码点(即字符)的方法,以及处理 Unicode 代码单元(即char值)的方法。
 * @author  Lee Boynton
 * @author  Arthur van Hoff
 * @author  Martin Buchholz
 * @author  Ulf Zibis
 * @see     java.lang.Object#toString()
 * @see     java.lang.StringBuffer
 * @see     java.lang.StringBuilder
 * @see     java.nio.charset.Charset
 * @since   JDK1.0
 */

 二.String的类图:

    a).一个Comparable,这个接口对实现他的每个对象都可按照一定的规则来进行排序,详情请点击下面链接

          JDK1.8源码学习--lang包(Comparable)_w5_Silence的博客-CSDN博客

    b).Secializable,这个接口是可为实现的对象进行序列化,详情请点击下面链接
                  ......(假装这个是链接,以后补充)

    c).Comparable,这个抽象类对一些数字操作进行了相关规范

        JDK1.8源码学习--lang包(Comparable)_w5_Silence的博客-CSDN博客

    三.内部类: 

                一个忽略大小写的比较器

    private static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
        // use serialVersionUID from JDK 1.2.2 for interoperability
        private static final long serialVersionUID = 8575799808933029326L;

        public int compare(String s1, String s2) {
            int n1 = s1.length();
            int n2 = s2.length();
            int min = Math.min(n1, n2);
            for (int i = 0; i < min; i++) {
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if (c1 != c2) {
                    c1 = Character.toUpperCase(c1);
                    c2 = Character.toUpperCase(c2);
                    if (c1 != c2) {
                        c1 = Character.toLowerCase(c1);
                        c2 = Character.toLowerCase(c2);
                        if (c1 != c2) {
                            // No overflow because of numeric promotion
                            return c1 - c2;
                        }
                    }
                }
            }
            return n1 - n2;
        }

        /** Replaces the de-serialized object. */
        //替换反序列化的对象
        private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
    }

四.成员变量:  

    /** The value is used for character storage. */
    //该值用于字符存储。
    private final char value[];

    /** Cache the hash code for the string */
    //缓存字符串的哈希码
    private int hash; // Default to 0

    /**l.
     *1. 类 String 是序列化流协议中的特例
     * 2.根据<a href="{@docRoot}..platformserializationspecoutput.html">对象序列化规范,
     * 第 6.2 节,“流元素”,将 String 实例写入 ObjectOutputStream
     */
    private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];


    /**
     * 1.一个比较器,按compareToIgnoreCase对String对象进行排序。这个比较器是可序列化的。
     * 2.请注意,此 Comparator 不会考虑语言环境,并且会导致某些语言环境的排序不令人满意。
     * java.text 包提供了 Collators以允许区分区域设置的排序
     */
    public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();

五.构造方法: 

                

    /**
     * 1.初始化一个新创建的 String对象,使其表示一个空字符序列。
     * 请注意,由于字符串是不可变的,因此不需要使用此构造函数。
     */
    public String() {
        this.value = "".value;
    }

    /**
     * 1.初始化一个新创建的String对象,使其表示与参数相同的字符序列;
     * 换句话说,新创建的字符串是参数字符串的副本。除非需要original的显式副本,
     * 否则不需要使用此构造函数,因为字符串是不可变的。
     */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

    /**
     * 1.分配一个新的String以表示当前包含在字符数组参数中的字符序列。
     * 复制字符数组的内容;字符数组的后续修改不会影响新创建的字符串
     */
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

    /**
     * 1.分配一个新的 String,其中包含来自字符数组参数的子数组的字符。offset参数是子数组第一个字符的索引,
     * count参数指定子数组的长度。复制子数组的内容;字符数组的后续修改不会影响新创建的字符串。
     */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

    /**
     * 1.分配一个新的String,其中包含来自 <a href="Character.htmlunicode">Unicode
     * 代码点数组参数的子数组的字符。offset参数是子数组第一个代码点的索引,count参数指定子数组的长度。
     * 子数组的内容转换为(char)s;int数组的后续修改不会影响新创建的字符串
     */
    public String(int[] codePoints, int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= codePoints.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > codePoints.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }

        final int end = offset + count;

        // Pass 1: Compute precise size of char[]
        //计算 char[] 的精确大小
        int n = count;
        for (int i = offset; i < end; i++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))
                continue;
            else if (Character.isValidCodePoint(c))
                n++;
            else throw new IllegalArgumentException(Integer.toString(c));
        }

        // Pass 2: Allocate and fill in char[]
        final char[] v = new char[n];

        for (int i = offset, j = 0; i < end; i++, j++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))
                v[j] = (char)c;
            else
                Character.toSurrogates(c, v, j++);
        }

        this.value = v;
    }

    /**
     * 1.分配从 8 位整数值数组的子数组构造的新String。
     * 2.offset参数是子数组第一个字节的索引,count参数指定子数组的长度。
     * 3.子数组中的每个byte都被转换为上面方法中指定的  char。
     * 4.此方法不能正确地将字节转换为字符。从 JDK 1.1 开始,执行此操作的首选方法是通过采用
     * java.nio.charset.Charset、字符集名称或使用平台默认字符集的String构造函数。
     */
    @Deprecated
    public String(byte ascii[], int hibyte, int offset, int count) {
        checkBounds(ascii, offset, count);
        char value[] = new char[count];

        if (hibyte == 0) {
            for (int i = count; i-- > 0;) {
                value[i] = (char)(ascii[i + offset] & 0xff);
            }
        } else {
            hibyte <<= 8;
            for (int i = count; i-- > 0;) {
                value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
            }
        }
        this.value = value;
    }

    /**
     * 1.分配一个新的String,其中包含从 8 位整数值数组构造的字符。
     * 结果字符串中的每个字符c都是从字节数组中的相应组件b构造的,这样:
     */
    @Deprecated
    public String(byte ascii[], int hibyte) {
        this(ascii, hibyte, 0, ascii.length);
    }


    /**
     * 1.通过使用指定的字符集解码指定的字节子数组来构造一个新的 String。
     * 新的String的长度是字符集的函数,因此可能不等于子数组的长度。

     * 2.当给定字节在给定字符集中无效时,此构造函数的行为未指定。
     * 当需要对解码过程进行更多控制时,应使用 java.nio.charset.CharsetDecoder类。
     */
    public String(byte bytes[], int offset, int length, String charsetName)
            throws UnsupportedEncodingException {
        if (charsetName == null)
            throw new NullPointerException("charsetName");
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(charsetName, bytes, offset, length);
    }

    /**
     * 1.通过使用指定的 java.nio.charset.Charset charset解码指定的字节子数组来构造一个新的String。
     * 新的String的长度是字符集的函数,因此可能不等于子数组的长度

     * 2.此方法始终使用此字符集的默认替换字符串替换格式错误的输入和不可映射的字符序列。
     * 当需要对解码过程进行更多控制时,应使用java.nio.charset.CharsetDecoder类。
     */
    public String(byte bytes[], int offset, int length, Charset charset) {
        if (charset == null)
            throw new NullPointerException("charset");
        checkBounds(bytes, offset, length);
        this.value =  StringCoding.decode(charset, bytes, offset, length);
    }

    /**
     * 1.通过使用指定的 java.nio.charset.Charset解码指定的字节数组来构造新的 String。
     * 新的 String的长度是字符集的函数,因此可能不等于字节数组的长度。

     * 2.当给定字节在给定字符集中无效时,此构造函数的行为未指定。
     * 当需要对解码过程进行更多控制时,应使用 java.nio.charset.CharsetDecoder 类。
     */
    public String(byte bytes[], String charsetName)
            throws UnsupportedEncodingException {
        this(bytes, 0, bytes.length, charsetName);
    }

    /**
     * 1.通过使用指定的 java.nio.charset.Charset解码指定的字节数组来构造新的String。
     * 新的String的长度是字符集的函数,因此可能不等于字节数组的长度。
     * 2.此方法始终使用此字符集的默认替换字符串替换格式错误的输入和不可映射的字符序列。
     * 当需要对解码过程进行更多控制时,应使用java.nio.charset.CharsetDecoder类。
     */
    public String(byte bytes[], Charset charset) {
        this(bytes, 0, bytes.length, charset);
    }

    /**
     * 1.通过使用平台的默认字符集解码指定的字节子数组来构造一个新的 String。
     * 新的String的长度是字符集的函数,因此可能不等于子数组的长度。
 
     * 2.当给定字节在默认字符集中无效时,此构造函数的行为未指定。当需要对解码过程进行更多控制时,
     * 应使用java.nio.charset.CharsetDecoder类。
     */
    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

    /**
     * 1.通过使用平台的默认字符集解码指定的字节数组来构造一个新的 String。
     * 新的String的长度是字符集的函数,因此可能不等于字节数组的长度

     * 2.当给定字节在默认字符集中无效时,此构造函数的行为未指定。当需要对解码过程进行更多控制时,
     * 应使用 java.nio.charset.CharsetDecoder类。
     */
    public String(byte bytes[]) {
        this(bytes, 0, bytes.length);
    }

    /**
     * 1.分配一个新字符串,该字符串包含当前包含在字符串缓冲区参数中的字符序列。
     * 复制字符串缓冲区的内容;字符串缓冲区的后续修改不会影响新创建的字符串。
     */
    public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }

    /**
     * 1.分配一个新字符串,该字符串包含当前包含在字符串构建器参数中的字符序列。
     * 复制字符串生成器的内容;字符串生成器的后续修改不会影响新创建的字符串。

     * 2.提供此构造函数是为了简化到StringBuilder的迁移。
     * 通过toString 方法从字符串生成器获取字符串可能会运行得更快,并且通常是首选。
     */
    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }

    /*
    * //包私有构造函数,它共享值数组以提高速度。这个构造函数总是期望使用 share==true 调用。
    * 需要一个单独的构造函数,因为我们已经有一个公共 String(char[]) 构造函数,它可以复制给定的 char[]。
    */
    String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }

六.内部方法:

                length

    /**
     * 1.返回此字符串的长度。长度等于字符串中Unicode 代码单元的数量。
     */
    public int length() {
        return value.length;
    }

                isEmpty

    /**
     * 1.当且仅当length() 为 0时才返回true
     */
    public boolean isEmpty() {
        return value.length == 0;
    }

                charAt

    /**
     * 1.返回指定索引处的 char值。索引范围从0到length() - 1。
     * 序列的第一个 char值位于索引 0处,下一个位于索引 1处,依此类推,对于数组索引
     * 2.如果索引指定的char值为 href="Character.htmlunicode">surrogate,则返回代理值。
     */
    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

                codePointAt/codePointBefore/codePointCount

    /**
     * 1.返回指定索引处的字符(Unicode 代码点)。索引指的是 char值(Unicode 代码单元),
     * 范围从 0到 length() - 1。
     * 2.如果给定索引处指定的 char值在高代理范围内,则后面的索引小于此String的长度,
     * 并且后面索引处的char值是在低代理范围内,则返回与该代理对对应的补充代码点。
     * 否则,返回给定索引处的 char值。
     */
    public int codePointAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return Character.codePointAtImpl(value, index, value.length);
    }

    /**

     * 1.返回指定索引之前的字符(Unicode 代码点)。索引指的是char值(Unicode 代码单元),
     * 范围从 1到 CharSequence.length()。

     * 2.如果 (index - 1)} 处的char值在低代理范围内,则(index - 2)不为负,
     * 并且char处的char值code (index - 2)在高代理范围内,则返回代理对的补充代码点值。
     * 如果 index - 1处的 char值是未配对的低代理或高代理,则返回代理值
 
     */
    public int codePointBefore(int index) {
        int i = index - 1;
        if ((i < 0) || (i >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return Character.codePointBeforeImpl(value, index, 0);
    }

   /**
     * 1.返回此 String的指定文本范围内的 Unicode 代码点数。文本范围从指定的 beginIndex开始,
     * 并扩展到索引 endIndex - 1处的  char。因此文本范围的长度(以 char为单位)是 endIndex-beginIndex。
     * 文本范围内未配对的代理每个都算作一个代码点。
     */
    public int codePointCount(int beginIndex, int endIndex) {
        if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
            throw new IndexOutOfBoundsException();
        }
        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
    }

                offsetByCodePoint

    /**
     * 1.返回此 String中的索引,该索引从给定的index偏移 codePointOffset代码点。 
     * index和 codePointOffset给出的文本范围内的未配对代理每个都算作一个代码点。
     */
    public int offsetByCodePoints(int index, int codePointOffset) {
        if (index < 0 || index > value.length) {
            throw new IndexOutOfBoundsException();
        }
        return Character.offsetByCodePointsImpl(value, 0, value.length,
                index, codePointOffset);
    }

                getChars

   /**
     * 将此字符串中的字符复制到 dst 中,从 dstBegin 开始。此方法不执行任何范围检查。
     */
    void getChars(char dst[], int dstBegin) {
        System.arraycopy(value, 0, dst, dstBegin, value.length);
    }

   /**
     * 1.将此字符串中的字符复制到目标字符数组中
     * 2.要复制的第一个字符位于索引 srcBegin;要复制的最后一个字符位于索引 srcEnd-1 处
     * (因此要复制的字符总数为  srcEnd-srcBegin)。字符被复制到 dst的子数组中,
     * 从索引 dstBegin 开始到索引结束:dstBegin + (srcEnd-srcBegin) - 1 
     */
    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

                getBytes

    /**
     * 1.将此字符串中的字符复制到目标字节数组中。每个字节接收相应字符的 8 个低位。
     * 每个字符的高 8 位不被复制,也不以任何方式参与传输。

     * 2.要复制的第一个字符位于索引srcBegin;要复制的最后一个字符位于索引srcEnd-1处。
     * 要复制的字符总数为srcEnd-srcBegin。转换为字节的字符被复制到dst的子数组中,
     * 从索引dstBegin开始到索引结束:dstBegin + (srcEnd-srcBegin) - 1 
     * 3.此方法不能正确地将字符转换为字节。从 JDK 1.1 开始,
     * 执行此操作的首选方法是通过 getBytes()方法,该方法使用平台的默认字符集。
     */
    @Deprecated
    public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        Objects.requireNonNull(dst);

        int j = dstBegin;
        int n = srcEnd;
        int i = srcBegin;
        char[] val = value;   /* avoid getfield opcode */

        while (i < n) {
            dst[j++] = (byte)val[i++];
        }
    }

    /**

     * 1.使用命名字符集将此 String 编码为字节序列,并将结果存储到新的字节数组中。

     * 2.当此字符串无法在给定字符集中编码时,此方法的行为未指定。
     * 当需要对编码过程进行更多控制时,应使用java.nio.charset.CharsetEncoder类。
     */
    public byte[] getBytes(String charsetName)
            throws UnsupportedEncodingException {
        if (charsetName == null) throw new NullPointerException();
        return StringCoding.encode(charsetName, value, 0, value.length);
    }

    /**
     * 1.使用给定的java.nio.charset.Charset将此String编码为字节序列,并将结果存储到新的字节数组中
     * 2.此方法始终使用此字符集的默认替换字节数组替换格式错误的输入和不可映射的字符序列。
     * 当需要对编码过程进行更多控制时,应使用 java.nio.charset.CharsetEncoder 类。
     */
    public byte[] getBytes(Charset charset) {
        if (charset == null) throw new NullPointerException();
        return StringCoding.encode(charset, value, 0, value.length);
    }

    /**
     * 1.使用平台的默认字符集将此 String编码为字节序列,并将结果存储到新的字节数组中
     * 2.当此字符串无法在默认字符集中编码时,此方法的行为未指定。
     * 当需要对编码过程进行更多控制时,应使用java.nio.charset.CharsetEncoder类。
     */
    public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
    }

                equals

    /**
     * 将此字符串与指定的对象进行比较。结果是true当且仅当参数不是 null并且是一个 String对象,
     * 该对象表示与此对象相同的字符序列。
     */
    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

                contentEquals

    /**
     * 将此字符串与指定的StringBuffer进行比较。当且仅当此String表示与指定的 StringBuffer相同的字符序列时,
     * 结果为 true。此方法在StringBuffer上同步。
     */
    public boolean contentEquals(StringBuffer sb) {
        return contentEquals((CharSequence)sb);
    }

                equalsIgnoreCase

/**
     * 1.将此 String与另一个String进行比较,忽略大小写考虑。如果两个字符串的长度相同,
     * 并且两个字符串中对应的字符是相等的忽略大小写,则认为两个字符串是相等的忽略大小写。
     *2.如果以下至少一项为真,则两个字符 c1和  c2被认为是相同的忽略大小写:
     * 这两个字符相同(由 = = operator) 将方法java.lang.Character.toUpperCase(char)
     * 应用于每个字符产生相同的结果 
     * 将方法 java.lang.CharactertoLowerCase(char)应用于每个字符产生相同的结果 
     */
    public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
    }

                compareTo

    /**
     * the {@link #equals(Object)} method would return {@code true}.
     * 1.按字典顺序比较两个字符串。比较基于字符串中每个字符的 Unicode 值。
     * 此 String对象表示的字符序列按字典顺序与参数字符串表示的字符序列进行比较。
     * 如果此 String对象按字典顺序位于参数字符串之前,则结果为负整数。
     * 如果此String对象按字典顺序跟在参数字符串之后,则结果为正整数。
     * 如果字符串相等,则结果为零;compareTo恰好在 equals(Object)方法返回true时返回0。
     * 2.这是字典排序的定义。如果两个字符串不同,那么它们要么在对两个字符串都是有效索引的某个索引处具有不同的字符,
     * 要么它们的长度不同,或者两者都有。如果它们在一个或多个索引位置有不同的字符,让 >k 是最小的这样的索引;
     * 然后在位置k处的字符具有较小值的字符串,如使用 < 运算符所确定的,按字典顺序排在另一个字符串之前。

     * 3.在这种情况下,compareTo返回两个字符串中位置 k处的两个字符值的差值——即值:
     * this.charAt(k)-anotherString .charAt(k) 如果没有它们不同的索引位置,
     * 则较短的字符串按字典顺序排在较长的字符串之前。在这种情况下,compareTo返回字符串长度的差值——即值:
     * this.length()-anotherString.length() 
     */
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        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;
    }

   /**
     * 1.按字典顺序比较两个字符串,忽略大小写差异。此方法返回一个整数,
     * 其符号是使用字符串的规范化版本调用compareTo的符号,
     * 其中通过对每个字符调用 Character.toLowerCase(Character.toUpperCase(character))消除了大小写差异。
     * 2.请注意,此方法不考虑语言环境,并且会导致某些语言环境的排序不令人满意。
     * java.text 包提供了collators以允许区分区域设置的排序。
     */
    public int compareToIgnoreCase(String str) {
        return CASE_INSENSITIVE_ORDER.compare(this, str);
    }

                regionMatches

    /**
     * 1.测试两个字符串区域是否相等
     * 2.此String对象的子字符串与参数 other 的子字符串进行比较。如果这些子字符串表示相同的字符序列,则结果为真。
     * 要比较的此 String对象的子字符串从索引toffset开始,长度为len。要比较的 other 的子串从索引ooffset开始,
     * 长度为 len。
     */
    public boolean regionMatches(int toffset, String other, int ooffset,
            int len) {
        char ta[] = value;
        int to = toffset;
        char pa[] = other.value;
        int po = ooffset;
        // Note: toffset, ooffset, or len might be near -1>>>1.
        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) {
            return false;
        }
        while (len-- > 0) {
            if (ta[to++] != pa[po++]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 1.测试两个字符串区域是否相等
     * 2.此String对象的子字符串与参数other的子字符串进行比较。如果这些子字符串表示相同的字符序列,则
     * 结果为true,当且仅当ignoreCase为真时忽略大小写。要比较的此 String对象的子字符串从索引 toffset开始,
     * 长度为 len。要比较的 other的子串从索引 offset开始,长度为len。
     */
    public boolean regionMatches(boolean ignoreCase, int toffset,
            String other, int ooffset, int len) {
        char ta[] = value;
        int to = toffset;
        char pa[] = other.value;
        int po = ooffset;
        // Note: toffset, ooffset, or len might be near -1>>>1.
        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) {
            return false;
        }
        while (len-- > 0) {
            char c1 = ta[to++];
            char c2 = pa[po++];
            if (c1 == c2) {
                continue;
            }
            if (ignoreCase) {
    
                char u1 = Character.toUpperCase(c1);
                char u2 = Character.toUpperCase(c2);
                if (u1 == u2) {
                    continue;
                }
     
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

                startsWith

    /**
     * 1测试此字符串的从指定索引开始的子字符串是否以指定前缀开头。
     */
    public boolean startsWith(String prefix, int toffset) {
        char ta[] = value;
        int to = toffset;
        char pa[] = prefix.value;
        int po = 0;
        int pc = prefix.value.length;
        // Note: toffset might be near -1>>>1.
        if ((toffset < 0) || (toffset > value.length - pc)) {
            return false;
        }
        while (--pc >= 0) {
            if (ta[to++] != pa[po++]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 测试此字符串是否以指定的前缀开头。
     */
    public boolean startsWith(String prefix) {
        return startsWith(prefix, 0);
    }

                endsWith

/**
     * 测试此字符串是否以指定的后缀结尾
     */
    public boolean endsWith(String suffix) {
        return startsWith(suffix, value.length - suffix.value.length);
    }

                hashCode

   /**
     * Returns a hash code for this string.
     * 1.返回此字符串的哈希码
     * 2.String对象的哈希码计算为 s[0]31^(n-1) + s[1]31^(n-2) + ... + s[ n-1]使用int算术,
     * 其中s[i]是字符串的i个字符, n是长度的字符串,^表示取幂。空字符串的哈希值为零。)
     */
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

                indexOf

    /**
     * 1.返回此字符串中第一次出现指定字符的索引。如果在此String对象表示的字符序列中
     * 出现值为ch的字符,则返回第一个此类出现的索引(以 Unicode 代码单元表示)
     * 2.对于从 0 到 0xFFFF(含)范围内的ch值,这是最小的值k使得:
     * this.charAt(k) == ch为真。对于ch的其他值,它是最小的值k使得:
     * this.codePointAt(k) == ch 为真。在任一情况下,如果此字符串中没有出现此类字符,则返回-1。
     */
    public int indexOf(int ch) {
        return indexOf(ch, 0);
    }

    /**
     * 1.返回此字符串中第一次出现指定字符的索引,从指定索引开始搜索。
     *  2.如果值为ch的字符出现在此String对象表示的字符序列中,其索引不小于fromIndex,
     *  则返回第一个此类出现的索引
     * 3.fromIndex的值没有限制。如果它是负数,它与它为零的效果相同:可以搜索整个字符串。如
     * 果大于此字符串的长度,则效果与等于此字符串的长度相同:返回 {@code -1}。
     */
    public int indexOf(int ch, int fromIndex) {
        final int max = value.length;
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }

        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            //在这里处理大多数情况(ch 是 BMP 代码点或负值(无效代码点))
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }

    /**
     * 1.返回此字符串中第一次出现指定子字符串的索引。
     * 2.返回的索引是k的最小值,其中:this.startsWith(str,k)如果没有这样的值k存在,则返回-1。
     */
    public int indexOf(String str) {
        return indexOf(str, 0);
    }

    /**
     * 1.返回此字符串中第一次出现指定子字符串的索引,从指定索引开始
     * If no such value of <i>k</i> exists, then {@code -1} is returned.
     * 2.返回的索引是最小值k其中:k>= fromIndex &&this.startsWith(str,k) 如果 k不存在这样的值,
     * 则返回 -1。
     */
    public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

    /**
     * 由 String 和 AbstractStringBuilder 共享的代码进行搜索。源是被搜索的字符数组,目标是被搜索的字符串
     */
    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            String target, int fromIndex) {
        return indexOf(source, sourceOffset, sourceCount,
                       target.value, 0, target.value.length,
                       fromIndex);
    }

    /**
     * 由 String 和 StringBuffer 共享的代码进行搜索。源是被搜索的字符数组,目标是被搜索的字符串
     */
    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        if (fromIndex >= sourceCount) {
            return (targetCount == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            return fromIndex;
        }

        char first = target[targetOffset];
        int max = sourceOffset + (sourceCount - targetCount);

        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }

            /* Found first character, now look at the rest of v2 */
            if (i <= max) {
                int j = i + 1;
                int end = j + targetCount - 1;
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

                lastIndexOf

    /**
     * 1.返回此字符串中最后一次出现的指定字符的索引。
     * 对于从 0 到 0xFFFF(含)范围内的ch值,返回的索引(以 Unicode 代码单元表示)是最大值k使得:
     * this。 charAt(k) == ch为真。对于ch的其他值,它是最大值k使得:
     * this.codePointAt(k) == ch为真。在任一情况下,如果此字符串中没有出现此类字符,则返回-1。
     * String从最后一个字符开始向后搜索。
     */
    public int lastIndexOf(int ch) {
        return lastIndexOf(ch, value.length - 1);
    }

    /**
     * 1返回此字符串中最后一次出现的指定字符的索引,从指定的索引开始向后搜索。
     * 对于从 0 到 0xFFFF(含)范围内的 ch值,返回的索引是最大值k使得: 
     * (this.charAt(k) == ch) &&(k<= fromIndex) 为真。对于ch的其他值,它是最大值k使得:
     * (this.codePointAt(k) == ch)&&(k<= fromIndex)为真。在任一情况下,
     * 如果此字符串中的位置 fromIndex处或之前没有出现此类字符,则返回-1
     * <p>All indices are specified in {@code char} values
     * (Unicode code units).
     * 2所有索引均以char值(Unicode 代码单元)指定
     */
    public int lastIndexOf(int ch, int fromIndex) {
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            final char[] value = this.value;
            int i = Math.min(fromIndex, value.length - 1);
            for (; i >= 0; i--) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return lastIndexOfSupplementary(ch, fromIndex);
        }
    }

    /**
     * 1.返回此字符串中最后一次出现的指定子字符串的索引。空字符串“”的最后一次出现被认为出现在索引值this.length()处。
     * 2.返回的索引是k的最大值,其中:this.startsWith(str,k)如果没有这样的值k存在,则返回-1。
     */
    public int lastIndexOf(String str) {
        return lastIndexOf(str, value.length);
    }

    /**
     * 1.返回此字符串中最后一次出现的指定子字符串的索引,从指定索引开始向后搜索。
     * 2.返回的索引是最大值k其中:k<=fromIndex&&this.startsWith(str,k)如果k的值不存在,则返回-1
     */
    public int lastIndexOf(String str, int fromIndex) {
        return lastIndexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

    /**
     * 由 String 和 AbstractStringBuilder 共享的代码进行搜索。源是被搜索的字符数组,目标是被搜索的字符串。
     */
    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            String target, int fromIndex) {
        return lastIndexOf(source, sourceOffset, sourceCount,
                       target.value, 0, target.value.length,
                       fromIndex);
    }

    /**
     * 由 String 和 StringBuffer 共享的代码进行搜索。源是被搜索的字符数组,目标是被搜索的字符串
     */
    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        /*
         * Check arguments; return immediately where possible. For
         * consistency, don't check for null str.
         * 检查参数;在可能的情况下立即返回。为了一致性,不要检查空字符串。
         */
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0) {
            return -1;
        }
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }
        /* Empty string always matches. */
        //空字符串始终匹配
        if (targetCount == 0) {
            return fromIndex;
        }

        int strLastIndex = targetOffset + targetCount - 1;
        char strLastChar = target[strLastIndex];
        int min = sourceOffset + targetCount - 1;
        int i = min + fromIndex;

    startSearchForLastChar:
        while (true) {
            while (i >= min && source[i] != strLastChar) {
                i--;
            }
            if (i < min) {
                return -1;
            }
            int j = i - 1;
            int start = j - (targetCount - 1);
            int k = strLastIndex - 1;

            while (j > start) {
                if (source[j--] != target[k--]) {
                    i--;
                    continue startSearchForLastChar;
                }
            }
            return start - sourceOffset + 1;
        }
    }

                subString

    /**
     * 1.返回一个字符串,该字符串是此字符串的子字符串。子字符串从指定索引处的字符开始,并延伸到该字符串的末尾。
     */
    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

    /**
     * 返回一个字符串,该字符串是此字符串的子字符串。子字符串从指定的beginIndex开始,
     * 并扩展到索引endIndex - 1处的字符。因此子串的长度是endIndex-beginIndex
     */
    public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

                subSequence

    /**
     * 1.返回作为此序列子序列的字符序列

     * 2.以str.subSequence(begin, end)形式调用此方法的行为与调用 str.substring(begin, end )

     * 3.定义此方法以便String类可以实现CharSequence接口。
     */
    public CharSequence subSequence(int beginIndex, int endIndex) {
        return this.substring(beginIndex, endIndex);
    }

                concat

    /**
     * 1.将指定的字符串连接到此字符串的末尾。
     * 2.如果参数字符串的长度为0,则返回此String对象。否则,返回一个String对象,该对象表示一个字符序列,
     * 该字符序列是由该String对象表示的字符序列与参数字符串所表示的字符序列的串联。
     */
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

                replace


    /**
     * 1.返回通过用 newChar替换此字符串中所有出现的oldChar而产生的字符串

     * 2.如果字符oldChar没有出现在这个String对象表示的字符序列中,那么返回一个对这个String对象的引用。
     * 否则,返回一个String对象,该对象表示与此String对象表示的字符序列相同的字符序列,除了oldChar的每次出现都被
     *  的出现替换新字符。
     */
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

                matches

    /**
     * 1.判断此字符串是否匹配给定的<a href="..utilregexPattern.htmlsum">正则表达式<a>
     * 2.以 str.matches(regex)形式调用此方法会产生与表达式完全相同的结果
     */
    public boolean matches(String regex) {
        return Pattern.matches(regex, this);
    }

                contains

    /**
     * 1.当且仅当此字符串包含指定的 char 值序列时才返回 true。
     */
    public boolean contains(CharSequence s) {
        return indexOf(s.toString()) > -1;
    }

                repalceFirst/All

    /**
     * 1.将此字符串的第一个子字符串与给定的<a href="..utilregexPattern.htmlsum">正则表达式替换为给定的替换。
     * 2.以str.replaceFirst(regex,repl)形式调用此方法会产生完全相同的结果结果作为表达式
     */
    public String replaceFirst(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
    }

    /**
     * 1.用给定的替换替换此字符串中与给定<a href="..utilregexPattern.htmlsum">正则表达式匹配的每个子字符串。
 
     * 2.以str.replaceAll(regex,repl)形式调用此方法会产生完全相同的结果结果作为表达式
     * 3.请注意,替换字符串中的反斜杠 \和美元符号 $可能会导致结果与将其视为文字替换字符串时的结果不同;
     * 见 java.util.regex.Matcher.replaceAll。如果需要,使用java.util.regex.Matcher.quoteReplacement取消这些字符的特殊含义
     */
    public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

    /**
     * 用指定的文字替换序列替换此字符串中与文字目标序列匹配的每个子字符串。
     * 替换从字符串的开头到结尾进行,例如,将字符串“aaa”中的“aa”替换为“b”将导致“ba”而不是“ab”
     */
    public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }

                        split

    /**
     * 1.围绕给定<a href="..utilregexPattern.htmlsum">正则表达式的匹配项拆分此字符串
     * 2.此方法返回的数组包含此字符串的每个子字符串,这些子字符串由与给定表达式匹配的另一个子字符串终止,或由字符串的末尾终止。
     * 数组中的子字符串按它们在此字符串中出现的顺序排列。如果表达式不匹配输入的任何部分,则结果数组只有一个元素,即这个字符串
     * 3.如果此字符串的开头存在正宽度匹配,则结果数组的开头将包含一个空的前导子字符串。
     * 然而,开头的零宽度匹配永远不会产生这样的空前导子串
     * 4.limit参数控制应用模式的次数,因此会影响结果数组的长度。如果限制 n大于零,
     * 则该模式将被应用至多n- 1 次,数组的长度将不大于n,并且数组的最后一个条目将包含最后一个匹配的分隔符之外的所有输入。
     * 如果 n为非正数,则该模式将被应用尽可能多的次数,并且数组可以具有任意长度。
     * 如果 n为零,则该模式将被应用尽可能多的次数,数组可以具有任意长度,并且将丢弃尾随的空字符串。
     *5.以str.split(regex,n)} 形式调用此方法会产生相同的结果作为表达式
     */
    public String[] split(String regex, int limit) {
        /* fastpath if the regex is a
         (1)one-char String and this character is not one of the
            RegEx's meta characters ".$|()[{^?*+\\", or
         (2)two-char String and the first char is the backslash and
            the second is not the ascii digit or ascii letter.
         */
        char ch = 0;
        if (((regex.value.length == 1 &&
             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
             (regex.length() == 2 &&
              regex.charAt(0) == '\\' &&
              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
              ((ch-'a')|('z'-ch)) < 0 &&
              ((ch-'A')|('Z'-ch)) < 0)) &&
            (ch < Character.MIN_HIGH_SURROGATE ||
             ch > Character.MAX_LOW_SURROGATE))
        {
            int off = 0;
            int next = 0;
            boolean limited = limit > 0;
            ArrayList<String> list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
                if (!limited || list.size() < limit - 1) {
                    list.add(substring(off, next));
                    off = next + 1;
                } else {    // last one
                    //assert (list.size() == limit - 1);
                    list.add(substring(off, value.length));
                    off = value.length;
                    break;
                }
            }
            // If no match was found, return this
            if (off == 0)
                return new String[]{this};

            // Add remaining segment
            if (!limited || list.size() < limit)
                list.add(substring(off, value.length));

            // Construct result
            int resultSize = list.size();
            if (limit == 0) {
                while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                    resultSize--;
                }
            }
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
        }
        return Pattern.compile(regex).split(this, limit);
    }

    /**
     * 2.此方法的工作方式类似于使用给定的表达式和零限制参数调用双参数 split(String, int)方法。
     * 因此,结果数组中不包含尾随空字符串
     */
    public String[] split(String regex) {
        return split(regex, 0);
    }

                join

    /**
     * 1.返回由CharSequence元素的副本与指定的分隔符的副本连接在一起的新字符串。
     *2.请注意,如果元素为空,则添加"null"。
     */
    public static String join(CharSequence delimiter, CharSequence... elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        // Number of elements not likely worth Arrays.stream overhead.
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs: elements) {
            joiner.add(cs);
        }
        return joiner.toString();
    }

    /**

     * 1.返回一个新的 String,它由 CharSequence元素 的副本与指定的delimiter的副本连接在一起组成

     * 2.请注意,如果单个元素为null,则添加"null"。
     */
    public static String join(CharSequence delimiter,
            Iterable<? extends CharSequence> elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs: elements) {
            joiner.add(cs);
        }
        return joiner.toString();
    }

                toLowerCase/UpperCase

    /**
     * 1.使用给定Locale的规则将此String中的所有字符转换为小写。大小写映射基于java.lang.Character类指定的 Unicode 标准版本。
     * 由于大小写映射并不总是 1:1 字符映射,因此生成的String可能与原始String的长度不同。
     */
    public String toLowerCase(Locale locale) {
        if (locale == null) {
            throw new NullPointerException();
        }

        int firstUpper;
        final int len = value.length;

        /* Now check if there are any characters that need to be changed. */
        //现在检查是否有任何字符需要更改
        scan: {
            for (firstUpper = 0 ; firstUpper < len; ) {
                char c = value[firstUpper];
                if ((c >= Character.MIN_HIGH_SURROGATE)
                        && (c <= Character.MAX_HIGH_SURROGATE)) {
                    int supplChar = codePointAt(firstUpper);
                    if (supplChar != Character.toLowerCase(supplChar)) {
                        break scan;
                    }
                    firstUpper += Character.charCount(supplChar);
                } else {
                    if (c != Character.toLowerCase(c)) {
                        break scan;
                    }
                    firstUpper++;
                }
            }
            return this;
        }

        char[] result = new char[len];
        int resultOffset = 0;  /* result may grow, so i+resultOffset
                                * is the write location in result
                                 result 可能会增长,所以 i+resultOffset 是 result 中的写入位置*/

        /* Just copy the first few lowerCase characters. */
        //只需复制前几个小写字符
        System.arraycopy(value, 0, result, 0, firstUpper);

        String lang = locale.getLanguage();
        //语言环境相关
        boolean localeDependent =
                (lang == "tr" || lang == "az" || lang == "lt");
        char[] lowerCharArray;
        int lowerChar;
        int srcChar;
        int srcCount;
        for (int i = firstUpper; i < len; i += srcCount) {
            srcChar = (int)value[i];
            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE
                    && (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                srcChar = codePointAt(i);
                srcCount = Character.charCount(srcChar);
            } else {
                srcCount = 1;
            }
            if (localeDependent ||
                srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA 希腊大写字母 SIGMA
                srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE 上面带点的拉丁文大写字母 I
                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
            } else {
                lowerChar = Character.toLowerCase(srcChar);
            }
            if ((lowerChar == Character.ERROR)
                    || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                if (lowerChar == Character.ERROR) {
                    lowerCharArray =
                            ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
                } else if (srcCount == 2) {
                    resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
                    continue;
                } else {
                    lowerCharArray = Character.toChars(lowerChar);
                }

                /* Grow result if needed */
                //如果需要,增加结果
                int mapLen = lowerCharArray.length;
                if (mapLen > srcCount) {
                    char[] result2 = new char[result.length + mapLen - srcCount];
                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                    result = result2;
                }
                for (int x = 0; x < mapLen; ++x) {
                    result[i + resultOffset + x] = lowerCharArray[x];
                }
                resultOffset += (mapLen - srcCount);
            } else {
                result[i + resultOffset] = (char)lowerChar;
            }
        }
        return new String(result, 0, len + resultOffset);
    }

    /**
     * 1.使用默认语言环境的规则将此String中的所有字符转换为小写。这相当于调用toLowerCase(Locale.getDefault())。

     * 2.注意:此方法对区域设置敏感,如果用于旨在独立解释区域设置的字符串,可能会产生意外结果。
     * 3.示例是编程语言标识符、协议密钥和 HTML 标签。
     * 例如,土耳其语语言环境中的 "TITLE".toLowerCase()返回"t\u005Cu0131tle",
     * 其中 '\u005Cu0131' 是拉丁小写字母无点 I 字符。要获得对区域设置不敏感的字符串的正确结果
     * 请使用 toLowerCase(Locale.ROOT)。
     */
    public String toLowerCase() {
        return toLowerCase(Locale.getDefault());
    }

    /**
     * 1.使用给定Locale的规则将此String中的所有字符转换为大写。
     * 大小写映射基于java.lang.Character类指定的 Unicode 标准版本。
     * 由于大小写映射并不总是 1:1 字符映射,因此生成的String可能与原始String的长度不同。
     * 2.区域敏感和 1:M 大小写映射的示例在下表中。
     */
    public String toUpperCase(Locale locale) {
        if (locale == null) {
            throw new NullPointerException();
        }

        int firstLower;
        final int len = value.length;

        /* Now check if there are any characters that need to be changed. */
        scan: {
            for (firstLower = 0 ; firstLower < len; ) {
                int c = (int)value[firstLower];
                int srcCount;
                if ((c >= Character.MIN_HIGH_SURROGATE)
                        && (c <= Character.MAX_HIGH_SURROGATE)) {
                    c = codePointAt(firstLower);
                    srcCount = Character.charCount(c);
                } else {
                    srcCount = 1;
                }
                int upperCaseChar = Character.toUpperCaseEx(c);
                if ((upperCaseChar == Character.ERROR)
                        || (c != upperCaseChar)) {
                    break scan;
                }
                firstLower += srcCount;
            }
            return this;
        }

        /* result may grow, so i+resultOffset is the write location in result */
        int resultOffset = 0;
        char[] result = new char[len]; /* may grow */

        /* Just copy the first few upperCase characters. */
        System.arraycopy(value, 0, result, 0, firstLower);

        String lang = locale.getLanguage();
        boolean localeDependent =
                (lang == "tr" || lang == "az" || lang == "lt");
        char[] upperCharArray;
        int upperChar;
        int srcChar;
        int srcCount;
        for (int i = firstLower; i < len; i += srcCount) {
            srcChar = (int)value[i];
            if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
                (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
                srcChar = codePointAt(i);
                srcCount = Character.charCount(srcChar);
            } else {
                srcCount = 1;
            }
            if (localeDependent) {
                upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
            } else {
                upperChar = Character.toUpperCaseEx(srcChar);
            }
            if ((upperChar == Character.ERROR)
                    || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
                if (upperChar == Character.ERROR) {
                    if (localeDependent) {
                        upperCharArray =
                                ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
                    } else {
                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
                    }
                } else if (srcCount == 2) {
                    resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
                    continue;
                } else {
                    upperCharArray = Character.toChars(upperChar);
                }

                /* Grow result if needed */
                int mapLen = upperCharArray.length;
                if (mapLen > srcCount) {
                    char[] result2 = new char[result.length + mapLen - srcCount];
                    System.arraycopy(result, 0, result2, 0, i + resultOffset);
                    result = result2;
                }
                for (int x = 0; x < mapLen; ++x) {
                    result[i + resultOffset + x] = upperCharArray[x];
                }
                resultOffset += (mapLen - srcCount);
            } else {
                result[i + resultOffset] = (char)upperChar;
            }
        }
        return new String(result, 0, len + resultOffset);
    }

    /**
     * 1.使用默认语言环境的规则将此String中的所有字符转换为大写。此方法等效于toUpperCase(Locale.getDefault())。
     * 2.注意:此方法对区域设置敏感,如果用于旨在独立解释区域设置的字符串,可能会产生意外结果
     * 3.示例是编程语言标识符、协议密钥和 HTML 标签。例如,土耳其语语言环境中的 "title".toUpperCase()
     * 返回"T\u005Cu0130TLE",其中 '\u005Cu0130' 是拉丁文大写字母 I 和 DOT ABOVE 字符。
     * 要获得对区域设置不敏感的字符串的正确结果,请使用toUpperCase(Locale.ROOT)
     */
    public String toUpperCase() {
        return toUpperCase(Locale.getDefault());
    }

                trim

    /**
     * 1.返回一个字符串,其值为该字符串,删除任何前导和尾随空格
     * 2.如果此  String} 对象表示一个空字符序列,或者此 String对象表示的字符序列的首尾字符都具有大于'\u005Cu0020'
     *  (空格字符)的代码,然后返回对此String对象的引用。

     * 3.否则,如果字符串中没有代码大于'\u005Cu0020'的字符,则返回一个表示空字符串的String对象。
     * 4.否则,让 k为代码大于'\u005Cu0020'的字符串中第一个字符的索引,并让m为最后一个字符的索引
     * 在代码大于 '\u005Cu0020'的字符串中。返回一个String对象,表示这个字符串的子串,
     * 以索引k处的字符开始,以索引m处的字符结束——即结果this.substring(k, m + 1)。
     * 5.此方法可用于从字符串的开头和结尾修剪空格(如上定义)
     */
    public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        while ((st < len) && (val[len - 1] <= ' ')) {
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    }

                toString

    /**
     * 这个对象(它已经是一个字符串!)本身被返回.
     */
    public String toString() {
        return this;
    }

                toCharArray

    /**
     * 将此字符串转换为新的字符数组
     */
    public char[] toCharArray() {
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }

                format

    /**

     * 1.使用指定的格式字符串和参数返回格式化的字符串。

     * 2.始终使用的语言环境是由java.util.Locale.getDefault()返回的语言环境

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

                valueOf

    /**
     * 返回 Object参数的字符串表示形式。
     */
    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }

    /**
     * 返回 char数组参数的字符串表示形式。复制字符数组的内容;字符数组的后续修改不会影响返回的字符串
     */
    public static String valueOf(char data[]) {
        return new String(data);
    }

    /**
     * 1.返回 char数组参数的特定子数组的字符串表示形式。
     *2.offset参数是子数组第一个字符的索引。count参数指定子数组的长度。
     * 复制子数组的内容;字符数组的后续修改不会影响返回的字符串。
     */
    public static String valueOf(char data[], int offset, int count) {
        return new String(data, offset, count);
    }

    /**
     * 相当于valueOf(char[], int, int)。
     */
    public static String copyValueOf(char data[], int offset, int count) {
        return new String(data, offset, count);
    }

    /**
     * 相当于 valueOf(char[])。
     */
    public static String copyValueOf(char data[]) {
        return new String(data);
    }

    /**
     * 返回 boolean参数的字符串表示形式
     */
    public static String valueOf(boolean b) {
        return b ? "true" : "false";
    }

    /**
     * 返回 char参数的字符串表示形式。
     */
    public static String valueOf(char c) {
        char data[] = {c};
        return new String(data, true);
    }

    /**
     * 返回 int参数的字符串表示形式。表示正是由一个参数的 Integer.toString方法返回的表示。
     */
    public static String valueOf(int i) {
        return Integer.toString(i);
    }

    /**
     * 返回long参数的字符串表示形式。表示正是由一个参数的Long.toString方法返回的表示。
     */
    public static String valueOf(long l) {
        return Long.toString(l);
    }

    /**
     * 返回float参数的字符串表示形式。表示正是一个参数的Float.toString方法返回的表示。
     */
    public static String valueOf(float f) {
        return Float.toString(f);
    }

    /**
     * 返回 double参数的字符串表示形式。表示正是由一个参数的Double.toString方法返回的表示。
     */
    public static String valueOf(double d) {
        return Double.toString(d);
    }

                intern

   /**

     * 1.返回字符串对象的规范表示。

     * 2.字符串池最初是空的,由 String类私下维护。
     * 3.当调用 intern 方法时,如果池中已经包含一个字符串,该字符串等于由equals(Object)
     * 方法确定的此String对象,则返回池中的字符串。否则,此String对象将添加到池中,并返回对此String对象的引用。

     * 4.对于任意两个字符串s和t,s.intern() == t.intern()是true当且仅当 s.等于(t)是 true。
     * 5.所有文字字符串和字符串值常量表达式都被interned。字符串文字在Java™ 语言规范的第 3.10.5 节中定义
     */
    public native String intern();

七.总结  

                string,相信大家经常使用的类...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值