String源码详解

  1. /* 
  2.  * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 
  3.  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
  4.  */  
  5. package java.lang;  
  6.   
  7. import java.io.ObjectStreamField;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.nio.charset.Charset;  
  10. import java.util.ArrayList;  
  11. import java.util.Arrays;  
  12. import java.util.Comparator;  
  13. import java.util.Formatter;  
  14. import java.util.Locale;  
  15. import java.util.regex.Matcher;  
  16. import java.util.regex.Pattern;  
  17. import java.util.regex.PatternSyntaxException;  
  18.   
  19. /** 
  20.  * The <code>String</code> class represents character strings. All 
  21.  * string literals in Java programs, such as <code>"abc"</code>, are 
  22.  * implemented as instances of this class. 
  23.  * <p> 
  24.  * Strings are constant; their values cannot be changed after they 
  25.  * are created. String buffers support mutable strings. 
  26.  * Because String objects are immutable they can be shared. For example: 
  27.  * <p><blockquote><pre> 
  28.  *     String str = "abc"; 
  29.  * </pre></blockquote><p> 
  30.  * is equivalent to: 
  31.  * <p><blockquote><pre> 
  32.  *     char data[] = {'a', 'b', 'c'}; 
  33.  *     String str = new String(data); 
  34.  * </pre></blockquote><p> 
  35.  * Here are some more examples of how strings can be used: 
  36.  * <p><blockquote><pre> 
  37.  *     System.out.println("abc"); 
  38.  *     String cde = "cde"; 
  39.  *     System.out.println("abc" + cde); 
  40.  *     String c = "abc".substring(2,3); 
  41.  *     String d = cde.substring(1, 2); 
  42.  * </pre></blockquote> 
  43.  * <p> 
  44.  * The class <code>String</code> includes methods for examining 
  45.  * individual characters of the sequence, for comparing strings, for 
  46.  * searching strings, for extracting substrings, and for creating a 
  47.  * copy of a string with all characters translated to uppercase or to 
  48.  * lowercase. Case mapping is based on the Unicode Standard version 
  49.  * specified by the {@link java.lang.Character Character} class. 
  50.  * <p> 
  51.  * The Java language provides special support for the string 
  52.  * concatenation operator (&nbsp;+&nbsp;), and for conversion of 
  53.  * other objects to strings. String concatenation is implemented 
  54.  * through the <code>StringBuilder</code>(or <code>StringBuffer</code>) 
  55.  * class and its <code>append</code> method. 
  56.  * String conversions are implemented through the method 
  57.  * <code>toString</code>, defined by <code>Object</code> and 
  58.  * inherited by all classes in Java. For additional information on 
  59.  * string concatenation and conversion, see Gosling, Joy, and Steele, 
  60.  * <i>The Java Language Specification</i>. 
  61.  * 
  62.  * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor 
  63.  * or method in this class will cause a {@link NullPointerException} to be 
  64.  * thrown. 
  65.  * 
  66.  * <p>A <code>String</code> represents a string in the UTF-16 format 
  67.  * in which <em>supplementary characters</em> are represented by <em>surrogate 
  68.  * pairs</em> (see the section <a href="Character.html#unicode">Unicode 
  69.  * Character Representations</a> in the <code>Character</code> class for 
  70.  * more information). 
  71.  * Index values refer to <code>char</code> code units, so a supplementary 
  72.  * character uses two positions in a <code>String</code>. 
  73.  * <p>The <code>String</code> class provides methods for dealing with 
  74.  * Unicode code points (i.e., characters), in addition to those for 
  75.  * dealing with Unicode code units (i.e., <code>char</code> values). 
  76.  * 
  77.  * @author  Lee Boynton 
  78.  * @author  Arthur van Hoff 
  79.  * @author  Martin Buchholz 
  80.  * @author  Ulf Zibis 
  81.  * @see     java.lang.Object#toString() 
  82.  * @see     java.lang.StringBuffer 
  83.  * @see     java.lang.StringBuilder 
  84.  * @see     java.nio.charset.Charset 
  85.  * @since   JDK1.0 
  86.  */  
  87.   
  88. /** 
  89.  * String类表示一类字符串,Java程序中的字符串都是当前类的实例,并且都是不可变的常量, 
  90.  * 它们一旦被创建就不能再被修改。字符串缓冲区支持可变的字符串, 
  91.  * 
  92.  */  
  93. public final class String  
  94.     implements java.io.Serializable, Comparable<String>, CharSequence {  
  95.     /** 用于存储当前字符串包含的字符 */  
  96.     private final char value[];  
  97.   
  98.     /** 用于缓存当前字符串的HashCod值,默认值为零**/  
  99.     private int hash;  
  100.   
  101.     private static final long serialVersionUID = -6849794470754667710L;  
  102.   
  103.     /** 
  104.      * 这个类主要用来提取序列化过程中某个对象内的字段【成员属性】元数据信息, 
  105.      * 包括字段的类型、类型代码、签名等 
  106.      */  
  107.     private static final ObjectStreamField[] serialPersistentFields =  
  108.             new ObjectStreamField[0];  
  109.   
  110.     /** 
  111.      * 初始化创建一个新的String对象用来表示一个空字符串。 
  112.      * 注意:完全没必要使用此构造器来创建一个String对象,因为String自身已经被设计为不可变 
  113.      */  
  114.     public String() {  
  115.         this.value = new char[0];  
  116.     }  
  117.   
  118.     /** 
  119.      * 通过传入一个字符串参数来构建一个空的String对象,换句话说,新创建的字符串对象是 
  120.      * 传入的字符串参数的一个副本。除非你确实需要显式的复制一个字符串对象,否则你完全 
  121.      * 没必要使用此构造器来创建一个String对象,因为String自身已经被设计为不可变 
  122.      * @param  original  原始的字符串对象 
  123.      */  
  124.     public String(String original) {  
  125.         this.value = original.value;  
  126.         this.hash = original.hash;  
  127.     }  
  128.   
  129.     /** 
  130.      * 通过传入的一个字符数组来构建一个空的String对象,新创建的String对象是传入的字符数组的 
  131.      * 一个副本,后续你对该字符数组对象的修改不会影响到当前新创建的String对象 
  132.      * @param  value  字符数组 
  133.      */  
  134.     public String(char value[]) {  
  135.         this.value = Arrays.copyOf(value, value.length);  
  136.     }  
  137.   
  138.     /** 
  139.      * 通过传入的一个字符数组并根据指定的offset和count参数来截取得到一个子字符数组, 
  140.      * 然后根据子字符数组来构建一个新的字符串对象,新创建的字符串对象是子字符数组内容的 
  141.      * 一个副本,后续你对该子字符数组内容的修改不会影响到当前新创建的字符串对象。其中offset 
  142.      * 参数表示截取子字符数组时在第一个参数即原字符数组中的起始偏移量,count表示子字符数组的长度。 
  143.      * @param  value    原字符数组 
  144.      * @param  offset  截取子字符数组时在原字符数组中的起始偏移量 
  145.      * @param  count   子字符数组的长度 
  146.      * 
  147.      * @throws  IndexOutOfBoundsException  如果offset或count参数越界了,那么会抛出此异常 
  148.      */  
  149.     public String(char value[], int offset, int count) {  
  150.         if (offset < 0) {  
  151.             throw new StringIndexOutOfBoundsException(offset);  
  152.         }  
  153.         if (count < 0) {  
  154.             throw new StringIndexOutOfBoundsException(count);  
  155.         }  
  156.         // 如果offset + count > value.length,则会抛出字符串越界异常  
  157.         if (offset > value.length - count) {  
  158.             throw new StringIndexOutOfBoundsException(offset + count);  
  159.         }  
  160.         this.value = Arrays.copyOfRange(value, offset, offset+count);  
  161.     }  
  162.   
  163.     /** 
  164.      * 通过传入的一个代码点数组并根据指定的offset和count参数来截取得到一个子字符数组, 
  165.      * 然后根据子字符数组来构建一个新的字符串对象,新创建的字符串对象是子字符数组内容的 
  166.      * 一个副本,后续你对该代码点数组内容的修改不会影响到当前新创建的字符串对象。其中offset 
  167.      * 参数表示在原代码点数组中截取的起始偏移量,count表示在原代码点数组中截取的元素长度。 
  168.      * 代码点最终会被转换成字符 
  169.      * @param  codePoints    原代码点数组 
  170.      * @param  offset       在原代码点数组中截取的起始偏移量 
  171.      * @param  count       在原代码点数组中截取的元素长度 
  172.      * 
  173.      * @throws  IndexOutOfBoundsException  如果offset或count参数越界了,那么会抛出此异常 
  174.      * @since  1.5 
  175.      */  
  176.     public String(int[] codePoints, int offset, int count) {  
  177.         if (offset < 0) {  
  178.             throw new StringIndexOutOfBoundsException(offset);  
  179.         }  
  180.         if (count < 0) {  
  181.             throw new StringIndexOutOfBoundsException(count);  
  182.         }  
  183.         // 如果offset + count > value.length,则会抛出字符串越界异常  
  184.         if (offset > codePoints.length - count) {  
  185.             throw new StringIndexOutOfBoundsException(offset + count);  
  186.         }  
  187.   
  188.         final int end = offset + count;  
  189.   
  190.         // 阶段1:计算char[]的精确大小  
  191.         int n = count;  
  192.         for (int i = offset; i < end; i++) {  
  193.             int c = codePoints[i];  
  194.             //判断一个代码点是否在基本多语言面(Basic Multilingual Plane,BMP)内  
  195.             if (Character.isBmpCodePoint(c)) {  
  196.                 continue;  
  197.             }  
  198.             //判断是否为一个合法的代码点  
  199.             else if (Character.isValidCodePoint(c)) {  
  200.                 n++;  
  201.             }  
  202.             else {  
  203.                 throw new IllegalArgumentException(Integer.toString(c));  
  204.             }  
  205.         }  
  206.   
  207.         // 阶段2:收集代码点、转换成字符char,并装入char[]  
  208.         final char[] v = new char[n];  
  209.         for (int i = offset, j = 0; i < end; i++, j++) {  
  210.             int c = codePoints[i];  
  211.             //判断一个代码点是否在基本多语言面(Basic Multilingual Plane,BMP)内  
  212.             if (Character.isBmpCodePoint(c)) {  
  213.                 // 将代码点转换成一个字符,BMP Code Point代码点是65535是2的16次方,  
  214.                 // 刚好是两个字节(即一个字)的大小。在超出两个字节后只能算是有效的代码点,  
  215.                 // 并非是BMP Code Point代码点。从代码中也可看出,BmpCodePoint代码点的整数是  
  216.                 // 可以直接强转成char类型的。在java中char类型刚好占2个字节,在2个字节以内的整数  
  217.                 // 都可以直接强转换成char类型  
  218.                 v[j] = (char) c;  
  219.             }  
  220.             else {  
  221.                 /** 
  222.                  * Surrogate这个概念,不是来自Java语言,而是来自Unicode编码方式之一:UTF-16。 
  223.                  * 具体请见: <a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16</a> 
  224.                  * 简而言之,Java语言內部的字符信息是使用UTF-16编码。因为char这个类型是16-bit的, 
  225.                  * 它可以有65536种取值,即65536个编号,每个编号可以代表1种字符。但是Unicode 
  226.                  * 包含的字符已经远远超过65536个。那编号大于65536的,还要用16-bit编码,该怎么办? 
  227.                  * 于是Unicode标准制定组想出的办法就是,从这65536个编号里,拿出2048个,规定它们是「Surrogates」, 
  228.                  * 让它们两个为一组,来代表编号大于65536的那些字符。更具体地, 
  229.                  * 编号从U+D800至U+DBFF的规定为「High Surrogates」,共1024个。 
  230.                  * 编号为 U+DC00至U+DFFF的规定为「Low Surrogates」,也是1024个, 
  231.                  * 它们两两组合出现,就又可以多表示1048576种字符。 
  232.                  */  
  233.                 Character.toSurrogates(c, v, j++);  
  234.             }  
  235.         }  
  236.         this.value = v;  
  237.     }  
  238.   
  239.     /** 
  240.      * 通过传入一个ASCII码的字节数组来构建一个新的字符串对象 
  241.      * 注意:此方法不能正确的将字节数组转成字符,自JDK1.1版本起,实现此功能更佳的方式是 
  242.      * 使用带charset(字符编码)参数的构造器来构建字符串对象,或者使用系统平台默认的字符集编码 
  243.      * 
  244.      * @param  ascii    用来转换成字符串的ASCII码的字节数组 
  245.      * @param  hibyte  每16位的Unicode编码单元的前8位 
  246.      * @param  offset  截取ASCII码的字节数组的起始偏移量 
  247.      * @param  count   在ASCII码的字节数组中截取的元素长度 
  248.      * 
  249.      * @throws  IndexOutOfBoundsException  如果offset或count参数越界了,那么会抛出此异常 
  250.      * 
  251.      * @see  #String(byte[], int) 
  252.      * @see  #String(byte[], int, int, java.lang.String) 
  253.      * @see  #String(byte[], int, int, java.nio.charset.Charset) 
  254.      * @see  #String(byte[], int, int) 
  255.      * @see  #String(byte[], java.lang.String) 
  256.      * @see  #String(byte[], java.nio.charset.Charset) 
  257.      * @see  #String(byte[]) 
  258.      */  
  259.     @Deprecated  
  260.     public String(byte ascii[], int hibyte, int offset, int count) {  
  261.         checkBounds(ascii, offset, count);  
  262.         char value[] = new char[count];  
  263.         //高8位如果是零,说明是正数  
  264.         if (hibyte == 0) {  
  265.             for (int i = count; i-- > 0;) {  
  266.                 //因为byte的取值范围是 -128~127,而Char是0~65535  
  267.                 //所以需要将前8位全部清为零,从而使得byte原来的负值变成正值  
  268.                 //0xff的二进制为1111 1111  
  269.                 value[i] = (char)(ascii[i + offset] & 0xff);  
  270.             }  
  271.         } else {  
  272.             // <<=带符号的左移动运算,向左移动8位,则最右边的8位全部清零  
  273.             hibyte <<= 8;  
  274.             for (int i = count; i-- > 0;) {  
  275.                 value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));  
  276.             }  
  277.         }  
  278.         this.value = value;  
  279.     }  
  280.   
  281.     /** 
  282.      * 通过传入一个ASCII码的字节数组来构建一个新的字符串对象, 
  283.      * 直接从offset偏移量位置截取到字节数组的末尾 
  284.      * @param ascii     用来转换成字符串的ASCII码的字节数组 
  285.      * @param hibyte    每16位的Unicode编码单元的前8位 
  286.      */  
  287.     @Deprecated  
  288.     public String(byte ascii[], int hibyte) {  
  289.         this(ascii, hibyte, 0, ascii.length);  
  290.     }  
  291.   
  292.     /** 
  293.      * 检查offset,count参数在字节数组中是否越界的工具方法 
  294.      * @param bytes     目标字节数组 
  295.      * @param offset    起始偏移量 
  296.      * @param length    截取长度 
  297.      */  
  298.     private static void checkBounds(byte[] bytes, int offset, int length) {  
  299.         if (length < 0)  
  300.             throw new StringIndexOutOfBoundsException(length);  
  301.         if (offset < 0)  
  302.             throw new StringIndexOutOfBoundsException(offset);  
  303.         if (offset > bytes.length - length)  
  304.             throw new StringIndexOutOfBoundsException(offset + length);  
  305.     }  
  306.   
  307.     /** 
  308.      * 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码 
  309.      * 解码为一个字符串对象 
  310.      * @param bytes         字节数组 
  311.      * @param offset        截取起始偏移量 
  312.      * @param length        截取的长度 
  313.      * @param charsetName   字符集编码 
  314.      * @throws UnsupportedEncodingException 
  315.      */  
  316.     public String(byte bytes[], int offset, int length, String charsetName)  
  317.             throws UnsupportedEncodingException {  
  318.         if (charsetName == null)  
  319.             throw new NullPointerException("charsetName");  
  320.         checkBounds(bytes, offset, length);  
  321.         this.value = StringCoding.decode(charsetName, bytes, offset, length);  
  322.     }  
  323.   
  324.     /** 
  325.      * 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码 
  326.      * 解码为一个字符串对象 
  327.      * @param bytes         字节数组 
  328.      * @param offset        截取起始偏移量 
  329.      * @param length        截取的长度 
  330.      * @param charset       字符集编码对象 
  331.      */  
  332.     public String(byte bytes[], int offset, int length, Charset charset) {  
  333.         if (charset == null)  
  334.             throw new NullPointerException("charset");  
  335.         checkBounds(bytes, offset, length);  
  336.         this.value =  StringCoding.decode(charset, bytes, offset, length);  
  337.     }  
  338.   
  339.     /** 
  340.      * 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码 
  341.      * 解码为一个字符串对象(重载) 
  342.      * 
  343.      * @since  JDK1.1 
  344.      */  
  345.     public String(byte bytes[], String charsetName)  
  346.             throws UnsupportedEncodingException {  
  347.         this(bytes, 0, bytes.length, charsetName);  
  348.     }  
  349.   
  350.     /** 
  351.      * 通过StringCoding类的decode方法将指定的字节数组按照指定的字符集编码 
  352.      * 解码为一个字符串对象(重载) 
  353.      * @since  1.6 
  354.      */  
  355.     public String(byte bytes[], Charset charset) {  
  356.         this(bytes, 0, bytes.length, charset);  
  357.     }  
  358.   
  359.     /** 
  360.      * 通过StringCoding类的decode方法将指定的字节数组按照系统平台 
  361.      * 的默认字符集编码解码为一个字符串对象(重载) 
  362.      * @since  1.6 
  363.      */  
  364.     public String(byte bytes[], int offset, int length) {  
  365.         checkBounds(bytes, offset, length);  
  366.         this.value = StringCoding.decode(bytes, offset, length);  
  367.     }  
  368.   
  369.     /** 
  370.      * 通过StringCoding类的decode方法将指定的字节数组按照系统平台 
  371.      * 的默认字符集编码解码为一个字符串对象(重载) 
  372.      * 这里没有指定offset,count参数,则默认会直接截取[0,length() -1]范围内的字节即 
  373.      * 默认会直接将整个字节数组解码为一个新的字符串对象 
  374.      * @since  1.6 
  375.      */  
  376.     public String(byte bytes[]) {  
  377.         this(bytes, 0, bytes.length);  
  378.     }  
  379.   
  380.   
  381.     /** 
  382.      * 根据传入的StringBuffer对象构造一个新的String对象,内部会将StringBuffer对象 
  383.      * 内的字符数组都复制到当前对象的value属性上,注意此方法是加锁的即线程安全的。 
  384.      * @param buffer 
  385.      */  
  386.     public String(StringBuffer buffer) {  
  387.         synchronized(buffer) {  
  388.             this.value = Arrays.copyOf(buffer.getValue(), buffer.length());  
  389.         }  
  390.     }  
  391.   
  392.     /** 
  393.      * 根据传入的StringBuilder对象构造一个新的String对象,内部会将StringBuilder对象 
  394.      * 内的字符数组都复制到当前对象的value属性上,注意此方法不是线程安全的。 
  395.      * @since  1.5 
  396.      */  
  397.     public String(StringBuilder builder) {  
  398.         this.value = Arrays.copyOf(builder.getValue(), builder.length());  
  399.     }  
  400.   
  401.   
  402.     String(char[] value, boolean share) {  
  403.         this.value = value;  
  404.     }  
  405.   
  406.     /** 
  407.      * 私有构造函数,建议使用String(char[],int,int)构造函数代替, 
  408.      * 此构造函数已被标记为废弃 
  409.      */  
  410.     @Deprecated  
  411.     String(int offset, int count, char[] value) {  
  412.         this(value, offset, count);  
  413.     }  
  414.   
  415.     /** 
  416.      * 返回一个字符串的长度,此长度必须等于Unicode编码单元的长度。 
  417.      * 一个Unicode编码单元为16个bit,而一个char字符占2个字节刚好16个bit,即 
  418.      * 一个字符串的长度等于它包含的字符个数。 
  419.      * 
  420.      * @return  返回当前字符串的长度 
  421.      */  
  422.     public int length() {  
  423.         return value.length;  
  424.     }  
  425.   
  426.     /** 
  427.      * 判断一个字符串是否为一个空字符串[""] 
  428.      * 当且仅当字符串的length()等于零,此方法才返回true,否则返回false 
  429.      * 
  430.      * @since 1.6 
  431.      */  
  432.     public boolean isEmpty() {  
  433.         return value.length == 0;  
  434.     }  
  435.   
  436.     /** 
  437.      * 返回字符串某个索引位置的字符 
  438.      * 
  439.      * @param      index   字符的索引位置,从零开始计算 
  440.      * @return     返回指定索引位置的字符 
  441.      * @exception  IndexOutOfBoundsException 
  442.      *             若index参数为负数或者index参数不小于length(),则会抛出索引越界异常 
  443.      */  
  444.     public char charAt(int index) {  
  445.         if ((index < 0) || (index >= value.length)) {  
  446.             throw new StringIndexOutOfBoundsException(index);  
  447.         }  
  448.         return value[index];  
  449.     }  
  450.   
  451.     /** 
  452.      * 返回字符串某个索引位置的Unicode code point(Unicode代码点) 
  453.      * 
  454.      * @param      index   字符的索引位置,从零开始计算 
  455.      * @return     返回指定索引位置的Unicode code point(Unicode代码点) 
  456.      * @exception  IndexOutOfBoundsException 
  457.      *             若index参数为负数或者index参数不小于length(),则会抛出索引越界异常 
  458.      * @since      1.5 
  459.      */  
  460.     public int codePointAt(int index) {  
  461.         if ((index < 0) || (index >= value.length)) {  
  462.             throw new StringIndexOutOfBoundsException(index);  
  463.         }  
  464.         return Character.codePointAtImpl(value, index, value.length);  
  465.     }  
  466.   
  467.     /** 
  468.      * 返回字符串某个索引位置之前的Unicode code point(Unicode代码点) 
  469.      * 
  470.      * @param      index   字符的索引位置,从零开始计算 
  471.      * @return     返回指定索引位置之前的Unicode code point(Unicode代码点) 
  472.      * @exception  IndexOutOfBoundsException 
  473.      *             若index参数小于1或者大于length(),则会抛出索引越界异常 
  474.      * @since      1.5 
  475.      */  
  476.     public int codePointBefore(int index) {  
  477.         int i = index - 1;  
  478.         if ((i < 0) || (i >= value.length)) {  
  479.             throw new StringIndexOutOfBoundsException(index);  
  480.         }  
  481.         return Character.codePointBeforeImpl(value, index, 0);  
  482.     }  
  483.   
  484.     /** 
  485.      * 返回字符串的指定区间内的Unicode code point(Unicode代码点)的总个数 
  486.      * 
  487.      * @param beginIndex   起始索引位置 
  488.      * @param endIndex    结束索引位置 
  489.      * @return            返回指定区间范围内的Unicode代码点的总个数 
  490.      * @exception IndexOutOfBoundsException 
  491.      *            若beginIndex参数为负数或endIndex参数大于length(), 
  492.      *            或者beginIndex参数大于endIndex参数,则会抛出索引越界异常 
  493.      * @since  1.5 
  494.      */  
  495.     public int codePointCount(int beginIndex, int endIndex) {  
  496.         if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {  
  497.             throw new IndexOutOfBoundsException();  
  498.         }  
  499.         return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);  
  500.     }  
  501.   
  502.     /** 
  503.      * index索引位置的字符往后偏移codePointOffset个索引位置,返回偏移后的索引位置 
  504.      * 
  505.      * @param index              某个字符的索引位置,是个基准点 
  506.      * @param codePointOffset    Unicode代码点的偏移量 
  507.      * @return  index    返回index索引位置偏移codePointOffset个Unicode代码点后新的索引位置 
  508.      * @exception IndexOutOfBoundsException 
  509.      *            若index参数为负数或大于length()或positive是正数且 
  510.      *            index索引位置后面的子字符串包含的Unicode代码点个数 
  511.      *            小于codePointOffset或codePointOffset是负数且index索引位置前面的 
  512.      *            子字符串包含的Unicode代码点个数小于codePointOffset参数的绝对值, 
  513.      *            则会抛出索引位置越界异常 
  514.      * @since 1.5 
  515.      */  
  516.     public int offsetByCodePoints(int index, int codePointOffset) {  
  517.         if (index < 0 || index > value.length) {  
  518.             throw new IndexOutOfBoundsException();  
  519.         }  
  520.         return Character.offsetByCodePointsImpl(value, 0, value.length,  
  521.                 index, codePointOffset);  
  522.     }  
  523.   
  524.     /** 
  525.      * 将当前字符串的字符复制到另一个目标字符数组中 
  526.      * @param dst         目标字符数组 
  527.      * @param dstBegin    复制的字符从目标字符数组的哪个索引位置开始放入 
  528.      */  
  529.     void getChars(char dst[], int dstBegin) {  
  530.         System.arraycopy(value, 0, dst, dstBegin, value.length);  
  531.     }  
  532.   
  533.     /** 
  534.      * 将当前字符串的[srcBegin,srcEnd)区间内的字符复制到dst[]目标字符数组内 
  535.      * dstbegin + (srcEnd-srcBegin) - 1 
  536.      * 
  537.      * @param      srcBegin   从原字符串的字符数组的哪个索引位置开始复制 
  538.      * @param      srcEnd     从原字符串的字符数组的哪个索引位置开始结束复制 
  539.      * @param      dst        字符复制到的哪个目标字符数组 
  540.      * @param      dstBegin   复制的字符从目标字符数组的哪个索引位置开始放入 
  541.      * @exception IndexOutOfBoundsException 
  542.      *            若srcBegin参数为负数或 
  543.      *            srcBegin参数大于srcEnd参数或 
  544.      *            srcEnd大于length()或 
  545.      *            dstBegin参数为负数或 
  546.      *            dstBegin + (srcEnd - srcBegin)表达式计算值大于dst.length(), 
  547.      *            则会抛出索引位置越界异常 
  548.      */  
  549.     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {  
  550.         if (srcBegin < 0) {  
  551.             throw new StringIndexOutOfBoundsException(srcBegin);  
  552.         }  
  553.         if (srcEnd > value.length) {  
  554.             throw new StringIndexOutOfBoundsException(srcEnd);  
  555.         }  
  556.         if (srcBegin > srcEnd) {  
  557.             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);  
  558.         }  
  559.         System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);  
  560.     }  
  561.   
  562.     /** 
  563.      * 将字符串的包含字符复制到一个目标的字节数组中。每个字节接收对应字符的低8位, 
  564.      * 而每个字符的高8位则不会被复制,也不会参与以任何方式的转换 
  565.      * 
  566.      * @deprecated  此方法不能准确的将字符转换成byte字节数组。 
  567.      *              自JDK1.1版本起,推荐使用String的getBytes()方法来代替, 
  568.      *              getBytes()方法默认会使用系统平台的默认字符集编码 
  569.      * 
  570.      * @param      srcBegin   从原字符串的字符数组的哪个索引位置开始复制 
  571.      * @param      srcEnd     从原字符串的字符数组的哪个索引位置开始结束复制 
  572.      * @param      dst        字符复制到的哪个目标字节数组 
  573.      * @param      dstBegin   复制的字符从目标字节数组的哪个索引位置开始放入 
  574.      * @exception IndexOutOfBoundsException 
  575.      *            若srcBegin参数为负数或 
  576.      *            srcBegin参数大于srcEnd参数或 
  577.      *            srcEnd大于length()或 
  578.      *            dstBegin参数为负数或 
  579.      *            dstBegin + (srcEnd - srcBegin)表达式计算值大于dst.length(), 
  580.      *            则会抛出索引位置越界异常 
  581.      */  
  582.     @Deprecated  
  583.     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {  
  584.         if (srcBegin < 0) {  
  585.             throw new StringIndexOutOfBoundsException(srcBegin);  
  586.         }  
  587.         if (srcEnd > value.length) {  
  588.             throw new StringIndexOutOfBoundsException(srcEnd);  
  589.         }  
  590.         if (srcBegin > srcEnd) {  
  591.             throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);  
  592.         }  
  593.         int j = dstBegin;  
  594.         int n = srcEnd;  
  595.         int i = srcBegin;  
  596.         /** 避免直接操作类的属性,使用方法中的局部变量代替引用可以减少getfield操作的次数,提高性能*/  
  597.         char[] val = value;  
  598.   
  599.         while (i < n) {  
  600.             dst[j++] = (byte)val[i++];  
  601.         }  
  602.     }  
  603.   
  604.     /** 
  605.      * 使用指定的字符集编码将String对象编码成一个字节数组 
  606.      * 若charsetName参数未指定,那么内部会抛出NullPointerException异常 
  607.      * 如果你想要更详细的控制字符编码的处理过程,那么你需要使用{@link java.nio.charset.CharsetEncoder}类 
  608.      * 
  609.      * @param  charsetName 
  610.      *         {@linkplain java.nio.charset.Charset}类支持的字符集编码名称 
  611.      * @return  返回String对象编码后的字节数组 
  612.      * @throws  UnsupportedEncodingException 
  613.      *          charset参数表示的不是合法的字符集编码名称, 
  614.      *          那么会抛出UnsupportedEncodingException异常 
  615.      * 
  616.      * @since  JDK1.1 
  617.      */  
  618.     public byte[] getBytes(String charsetName)  
  619.             throws UnsupportedEncodingException {  
  620.         if (charsetName == nullthrow new NullPointerException();  
  621.         return StringCoding.encode(charsetName, value, 0, value.length);  
  622.     }  
  623.   
  624.     /** 
  625.      * 方法同上,只是字符集编码参数改成了通过Charset类来提供 
  626.      * 
  627.      * @since  1.6 
  628.      */  
  629.     public byte[] getBytes(Charset charset) {  
  630.         if (charset == nullthrow new NullPointerException();  
  631.         return StringCoding.encode(charset, value, 0, value.length);  
  632.     }  
  633.   
  634.     /** 
  635.      * 同getBytes(String charsetName)方法类似,只是这里是采用系统平台默认的字符集编码 
  636.      * 对字符串进行编码 
  637.      * 
  638.      * @since      JDK1.1 
  639.      */  
  640.     public byte[] getBytes() {  
  641.         return StringCoding.encode(value, 0, value.length);  
  642.     }  
  643.   
  644.     /** 
  645.      * 比较两个对象是否相等,当且仅当anObject参数不为null且 
  646.      * 它与当前字符串对象表示的是同一个字符序列,才会返回true 
  647.      * 
  648.      * @param  anObject  与当前字符串对象进行比较的对象 
  649.      * @return  返回指定对象是否与当前字符串对象相等 
  650.      * 
  651.      * @see  #compareTo(String) 
  652.      * @see  #equalsIgnoreCase(String) 
  653.      */  
  654.     public boolean equals(Object anObject) {  
  655.         if (this == anObject) {  
  656.             return true;  
  657.         }  
  658.         //若anObject对象是String类型  
  659.         if (anObject instanceof String) {  
  660.             //强制转换成String对象  
  661.             String anotherString = (String) anObject;  
  662.             //获取当前字符串对象的字符序列并缓存到变量n上  
  663.             int n = value.length;  
  664.             //若两者的字符序列长度一致,则接下来要比较字符序列的每个字符是否相等  
  665.             if (n == anotherString.value.length) {  
  666.                 char v1[] = value;  
  667.                 char v2[] = anotherString.value;  
  668.                 int i = 0;  
  669.                 while (n-- != 0) {  
  670.                     //只要字符序列中存在一个字符不相等,则返回false即两者不相等  
  671.                     if (v1[i] != v2[i]) {  
  672.                         return false;  
  673.                     }  
  674.                     i++;  
  675.                 }  
  676.                 return true;  
  677.             }  
  678.         }  
  679.         return false;  
  680.     }  
  681.   
  682.     /** 
  683.      * 比较当前字符串的字符序列是否与指定的StringBuffer对象包含的字符序列相等 
  684.      * 
  685.      * @param  sb   与当前字符串对象进行比较的StringBuffer对象 
  686.      * @return  返回当前字符串对象是否与指定的StringBuffer对象相等 
  687.      * 
  688.      * @since  1.4 
  689.      */  
  690.     public boolean contentEquals(StringBuffer sb) {  
  691.         synchronized (sb) {  
  692.             return contentEquals((CharSequence) sb);  
  693.         }  
  694.     }  
  695.   
  696.     /** 
  697.      * 比较当前字符串的字符序列是否与指定的CharSequence对象包含的字符序列相等 
  698.      * @since  1.5 
  699.      */  
  700.     public boolean contentEquals(CharSequence cs) {  
  701.         if (value.length != cs.length())  
  702.             return false;  
  703.         // 若传入的参数是StringBuffer或StringBuilder类型  
  704.         if (cs instanceof AbstractStringBuilder) {  
  705.             char v1[] = value;  
  706.             char v2[] = ((AbstractStringBuilder) cs).getValue();  
  707.             int i = 0;  
  708.             int n = value.length;  
  709.             while (n-- != 0) {  
  710.                 if (v1[i] != v2[i])  
  711.                     return false;  
  712.                 i++;  
  713.             }  
  714.             return true;  
  715.         }  
  716.         // 若传入的参数是String类型  
  717.         if (cs.equals(this))  
  718.             return true;  
  719.         // 若传入的参数是通用的CharSequence类型  
  720.         char v1[] = value;  
  721.         int i = 0;  
  722.         int n = value.length;  
  723.         while (n-- != 0) {  
  724.             if (v1[i] != cs.charAt(i))  
  725.                 return false;  
  726.             i++;  
  727.         }  
  728.         return true;  
  729.     }  
  730.   
  731.     /** 
  732.      * 比较当前字符串的字符序列是否与指定的String对象包含的字符序列相等, 
  733.      * 此方法在比较过程中会忽略每个字符的大小写 
  734.      * 
  735.      * 当两个字符串c1和c2满足如下其中任意一个条件,则认为两者在忽略大小写的情况下相等: 
  736.      *     1. c1 == c2 返回true 
  737.      *     2. 对于两个字符串包含的字符序列中的每个字符调用java.lang.Character#toUpperCase(char)方法, 
  738.      *        若最终生成的结果相同,则认为两者相等 
  739.      *     3. 对于两个字符串包含的字符序列中的每个字符调用java.lang.Character#toLowerCase(char)方法, 
  740.      *        若最终生成的结果相同,则认为两者相等 
  741.      * @param  anotherString     与当前字符串对象进行比较的字符串对象 
  742.      * @return  返回两个字符串对象是否相等 
  743.      * 
  744.      * @see  #equals(Object) 
  745.      */  
  746.     public boolean equalsIgnoreCase(String anotherString) {  
  747.         return (this == anotherString) ? true  
  748.                 : (anotherString != null)  
  749.                 && (anotherString.value.length == value.length)  
  750.                 && regionMatches(true0, anotherString, 0, value.length);  
  751.     }  
  752.   
  753.     /** 
  754.      * 比较两个字符串的字母顺序 
  755.      * 这个比较操作是基于字符串对象的字符序列中包含的每个字符的Unicode值进行比较。 
  756.      * 如果当前字符串对象的字母顺序在字符串参数之前,那么返回结果为负数, 
  757.      * 如果当前字符串对象的字母顺序在字符串参数之后,那么返回结果为正数, 
  758.      * 如果当前字符串对象与字符串参数相等(即equals()返回true),那么返回结果为零 
  759.      * 
  760.      * @param   anotherString   the <code>String</code> to be compared. 
  761.      * @return  返回两个字符串的比较结果, 
  762.      *          正数表示当前字符串较大,负数表示当前字符串较小,否则表达两者相等 
  763.      */  
  764.     public int compareTo(String anotherString) {  
  765.         int len1 = value.length;  
  766.         int len2 = anotherString.value.length;  
  767.         //取两个字符串长度较小的那个长度  
  768.         int lim = Math.min(len1, len2);  
  769.         char v1[] = value;  
  770.         char v2[] = anotherString.value;  
  771.   
  772.         int k = 0;  
  773.         while (k < lim) {  
  774.             char c1 = v1[k];  
  775.             char c2 = v2[k];  
  776.             if (c1 != c2) {  
  777.                 return c1 - c2;  
  778.             }  
  779.             k++;  
  780.         }  
  781.         // 如果前lim个字符全部相等,那么此时就比较谁的字符串长度大,  
  782.         // 判定长度大的字符串比长度小的字符串大  
  783.         return len1 - len2;  
  784.     }  
  785.   
  786.     /** 
  787.      * 字符串忽略大小写比较器,此比较器实现了Serializable接口 
  788.      * 注意:此接口并没有考虑语言环境,对于部分地区可能会导致不满意的顺序, 
  789.      * java.text包下的Collators类提供了语言环境敏感的字符串顺序。 
  790.      * 
  791.      * @see     java.text.Collator#compare(String, String) 
  792.      * @since   1.2 
  793.      */  
  794.     public static final Comparator<String> CASE_INSENSITIVE_ORDER  
  795.                                          = new CaseInsensitiveComparator();  
  796.     private static class CaseInsensitiveComparator  
  797.             implements Comparator<String>, java.io.Serializable {  
  798.         private static final long serialVersionUID = 8575799808933029326L;  
  799.   
  800.         public int compare(String s1, String s2) {  
  801.             int n1 = s1.length();  
  802.             int n2 = s2.length();  
  803.             int min = Math.min(n1, n2);  
  804.             for (int i = 0; i < min; i++) {  
  805.                 char c1 = s1.charAt(i);  
  806.                 char c2 = s2.charAt(i);  
  807.                 if (c1 != c2) {  
  808.                     c1 = Character.toUpperCase(c1);  
  809.                     c2 = Character.toUpperCase(c2);  
  810.                     if (c1 != c2) {  
  811.                         c1 = Character.toLowerCase(c1);  
  812.                         c2 = Character.toLowerCase(c2);  
  813.                         if (c1 != c2) {  
  814.                             // 因为存在数字晋升机制,因此此处不会存在数据类型溢出问题  
  815.                             return c1 - c2;  
  816.                         }  
  817.                     }  
  818.                 }  
  819.             }  
  820.             return n1 - n2;  
  821.         }  
  822.     }  
  823.   
  824.     /** 
  825.      * 忽略大小写前提下比较两个字符串的字母顺序 
  826.      * 注意:此接口并没有考虑语言环境,对于部分地区可能会导致不满意的顺序, 
  827.      * java.text包下的Collators类提供了语言环境敏感的字符串顺序。 
  828.      * 
  829.      * @param   str   与当前字符串对象进行边角的字符串参数 
  830.      * @return 
  831.      *          返回负数表示指定的字符串对象大于当前字符串对象 
  832.      *          返回正数表示指定的字符串对象小于当前字符串对象 
  833.      *          返回零表示指定的字符串对象等于当前字符串对象 
  834.      * @see     java.text.Collator#compare(String, String) 
  835.      * @since   1.2 
  836.      */  
  837.     public int compareToIgnoreCase(String str) {  
  838.         return CASE_INSENSITIVE_ORDER.compare(this, str);  
  839.     }  
  840.   
  841.     /** 
  842.      * 比较两个字符串的指定区域内的字符序列是否相等 
  843.      * 注意:此方法并没有忽略字符大小写 
  844.      * @param   toffset      当前字符串截取的起始索引位置 
  845.      * @param   other        传入的另一个字符串对象 
  846.      * @param   ooffset      other参数表示的字符串对象的起始索引位置 
  847.      * @param   len          other参数表示的字符串对象的截取长度 
  848.      * @return  返回两个字符串的指定区域内的字符序列是否相等 
  849.      */  
  850.     public boolean regionMatches(int toffset, String other, int ooffset,  
  851.             int len) {  
  852.         char ta[] = value;  
  853.         int to = toffset;  
  854.         char pa[] = other.value;  
  855.         int po = ooffset;  
  856.         // Note: toffset, ooffset, or len might be near -1>>>1.  
  857.         if ((ooffset < 0) || (toffset < 0)  
  858.                 || (toffset > (long)value.length - len)  
  859.                 || (ooffset > (long)other.value.length - len)) {  
  860.             return false;  
  861.         }  
  862.         while (len-- > 0) {  
  863.             if (ta[to++] != pa[po++]) {  
  864.                 return false;  
  865.             }  
  866.         }  
  867.         return true;  
  868.     }  
  869.   
  870.     /** 
  871.      * 比较两个字符串的指定区域内的字符序列是否相等 
  872.      * 当且仅当满足以下其中任意一个提交, 
  873.      * 则判定两个字符串的指定区域内的字符序列不相等: 
  874.      *     1. toffset参数为负数 
  875.      *     2. ooffset参数为负数 
  876.      *     3. toffset + len大于当前字符串的长度 
  877.      *     4. ooffset + len大于other参数表示的字符串的长度 
  878.      *     5. ignoreCase=false且存在某些非负数K小于参数len, 
  879.      *        比如:this.charAt(toffset + k) != other.charAt(ooffset + k) 
  880.      *     6. ignoreCase=true且存在某些非负数K小于参数len, 
  881.      *        比如: Character.toLowerCase(this.charAt(toffset + k)) != 
  882.      *              Character.toLowerCase(other.charAt(ooffset + k)) 
  883.      * 
  884.      *              Character.toLowerCase(this.charAt(toffset+k)) != 
  885.      *              Character.toLowerCase(other.charAt(ooffset+k)) 
  886.      * 
  887.      *              Character.toUpperCase(this.charAt(toffset + k)) != 
  888.      *              Character.toUpperCase(other.charAt(ooffset + k)) 
  889.      * 
  890.      * @param   ignoreCase   比较过程中是否忽略大小写 
  891.      * @param   toffset      当前字符串截取的起始索引位置 
  892.      * @param   other        传入的另一个字符串对象 
  893.      * @param   ooffset      other参数表示的字符串对象的起始索引位置 
  894.      * @param   len          other参数表示的字符串对象的截取长度 
  895.      * @return  返回两个字符串的指定区域内的字符序列是否相等 
  896.      */  
  897.     public boolean regionMatches(boolean ignoreCase, int toffset,  
  898.             String other, int ooffset, int len) {  
  899.         char ta[] = value;  
  900.         int to = toffset;  
  901.         char pa[] = other.value;  
  902.         int po = ooffset;  
  903.         // Note: toffset, ooffset, or len might be near -1>>>1.  
  904.         if ((ooffset < 0) || (toffset < 0)  
  905.                 || (toffset > (long)value.length - len)  
  906.                 || (ooffset > (long)other.value.length - len)) {  
  907.             return false;  
  908.         }  
  909.         while (len-- > 0) {  
  910.             char c1 = ta[to++];  
  911.             char c2 = pa[po++];  
  912.             //如果两个字符相等,则跳过  
  913.             if (c1 == c2) {  
  914.                 continue;  
  915.             }  
  916.             //如果两个字符不相等,则要判断是否设置了忽略大小写  
  917.             if (ignoreCase) {  
  918.                 // 如果设置了忽略大小写,那么首先将两者统一转成大写再比较  
  919.                 char u1 = Character.toUpperCase(c1);  
  920.                 char u2 = Character.toUpperCase(c2);  
  921.                 //若转成大写后两者相等,那么跳过,继续比较下一个字符  
  922.                 if (u1 == u2) {  
  923.                     continue;  
  924.                 }  
  925.                 //非常不幸的是,Character.toUpperCase()在转换成大写时对于格鲁吉亚字母不能正常工作,  
  926.                 //因为格鲁吉亚字母拥有怪异的大小写转换规则,因此我们需要在当前循环退出之前再进行一次字符比较检查  
  927.                 if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {  
  928.                     continue;  
  929.                 }  
  930.             }  
  931.             // 若两个字符本身不相等且ignoreCase=false或  
  932.             // 两个字符本身不相等且ignoreCase=true,但是统一转换成大写形式后仍然不相等,  
  933.             // 此时应该返回false,即判定两个字符不相等  
  934.             return false;  
  935.         }  
  936.         //否则判定两个字符串的指定区域内的字符序列相等  
  937.         return true;  
  938.     }  
  939.   
  940.     /** 
  941.      * 检测当前字符串是否以指定的前缀字符串开头 
  942.      * 此方法等价于this.substring(toffset).startsWith(prefix) 
  943.      * @param   prefix    指定的字符串前缀 
  944.      * @param   toffset   起始偏移量 
  945.      * @return  若toffset参数为负数或者大于当前字符串的长度,则直接返回false 
  946.      */  
  947.     public boolean startsWith(String prefix, int toffset) {  
  948.         char ta[] = value;  
  949.         int to = toffset;  
  950.         char pa[] = prefix.value;  
  951.         int po = 0;  
  952.         int pc = prefix.value.length;  
  953.         // 若toffset为负数或toffset + prefix.length() > this.length(),则直接return false  
  954.         if ((toffset < 0) || (toffset > value.length - pc)) {  
  955.             return false;  
  956.         }  
  957.         while (--pc >= 0) {  
  958.             if (ta[to++] != pa[po++]) {  
  959.                 return false;  
  960.             }  
  961.         }  
  962.         return true;  
  963.     }  
  964.   
  965.     /** 
  966.      * 检测当前字符串是否以指定的前缀字符串开头(重载) 
  967.      * @param   prefix    指定的字符串前缀 
  968.      * @since   1. 0 
  969.      */  
  970.     public boolean startsWith(String prefix) {  
  971.         return startsWith(prefix, 0);  
  972.     }  
  973.   
  974.     /** 
  975.      * 检测当前字符串是否以指定的后缀字符串结尾 
  976.      * 
  977.      * @param   suffix   后缀字符串 
  978.      */  
  979.     public boolean endsWith(String suffix) {  
  980.         return startsWith(suffix, value.length - suffix.value.length);  
  981.     }  
  982.   
  983.     /** 
  984.      * 计算当前字符串的hashcode值,计算公式为: 
  985.      * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 
  986.      * 上面的n表示字符串的长度,^表示求幂运算 
  987.      * 空字符串""的hashcode值为零 
  988.      * 
  989.      * @return  返回当前字符串对象的hashcode值 
  990.      */  
  991.     public int hashCode() {  
  992.         int h = hash;  
  993.         if (h == 0 && value.length > 0) {  
  994.             char val[] = value;  
  995.   
  996.             for (int i = 0; i < value.length; i++) {  
  997.                 h = 31 * h + val[i];  
  998.             }  
  999.             hash = h;  
  1000.         }  
  1001.         return h;  
  1002.     }  
  1003.   
  1004.     /** 
  1005.      * 返回指定字符在当前字符串对象中第一次出现的索引位置 
  1006.      * 
  1007.      * @param   ch   Unicode code point表示的一个字符,取值范围为[0, 0xFFFF) 
  1008.      * @return  若指定字符在当前字符串的字符序列中不存在,则返回-1 
  1009.      */  
  1010.     public int indexOf(int ch) {  
  1011.         return indexOf(ch, 0);  
  1012.     }  
  1013.   
  1014.     /** 
  1015.      * 返回指定字符在当前字符串对象中第一次出现的索引位置 
  1016.      * 
  1017.      * @param   ch          Unicode code point表示的一个字符,取值范围为[0, 0xFFFF) 
  1018.      * @param   fromIndex   在当前字符串中查找的起始索引位置 
  1019.      * @return  若指定字符在当前字符串的字符序列中不存在,则返回-1 
  1020.      */  
  1021.     public int indexOf(int ch, int fromIndex) {  
  1022.         final int max = value.length;  
  1023.         if (fromIndex < 0) {  
  1024.             fromIndex = 0;  
  1025.         } else if (fromIndex >= max) {  
  1026.             return -1;  
  1027.         }  
  1028.   
  1029.         //若ch参数小于Unicode补充代码点的最小值0x010000  
  1030.         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {  
  1031.             // 查理大部分情况,比如ch参数是一个合法的BMP代码点,  
  1032.             // 或者ch是一个负数即非法的代码点  
  1033.             final char[] value = this.value;  
  1034.             for (int i = fromIndex; i < max; i++) {  
  1035.                 if (value[i] == ch) {  
  1036.                     return i;  
  1037.                 }  
  1038.             }  
  1039.             return -1;  
  1040.         } else {  
  1041.             //字符属于Unicode补充代码点情况  
  1042.             return indexOfSupplementary(ch, fromIndex);  
  1043.         }  
  1044.     }  
  1045.   
  1046.     /** 
  1047.      * 返回指定的代码点表示的字符在当前字符串中第一次出现的索引位置 
  1048.      * @param  fromIndex  从哪个索引位置开始查找 
  1049.      */  
  1050.     private int indexOfSupplementary(int ch, int fromIndex) {  
  1051.         if (Character.isValidCodePoint(ch)) {  
  1052.             final char[] value = this.value;  
  1053.             /** 
  1054.              * 一个完整的Unicode字符叫代码点CodePoint,而一个Java char叫代码单元code unit。 
  1055.              * String对象以UTF-16保存Unicode字符,需要用2个字符表示一个超大字符集的汉字, 
  1056.              * 这这种表示方式称之为Surrogate,第一个字符叫 Surrogate High,第二个就是 Surrogate Low 
  1057.              */  
  1058.             final char hi = Character.highSurrogate(ch);  
  1059.             final char lo = Character.lowSurrogate(ch);  
  1060.             final int max = value.length - 1;  
  1061.             for (int i = fromIndex; i < max; i++) {  
  1062.                 if (value[i] == hi && value[i + 1] == lo) {  
  1063.                     return i;  
  1064.                 }  
  1065.             }  
  1066.         }  
  1067.         return -1;  
  1068.     }  
  1069.   
  1070.     /** 
  1071.      * 返回指定代码点表示的字符在当前字符串对象中最后一次出现的索引位置 
  1072.      */  
  1073.     public int lastIndexOf(int ch) {  
  1074.         return lastIndexOf(ch, value.length - 1);  
  1075.     }  
  1076.   
  1077.     /** 
  1078.      * 返回指定的代码点表示的字符在当前字符串中最后一次出现的索引位置 
  1079.      * 与indexOf方法类似 
  1080.      */  
  1081.     public int lastIndexOf(int ch, int fromIndex) {  
  1082.         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {  
  1083.             final char[] value = this.value;  
  1084.             int i = Math.min(fromIndex, value.length - 1);  
  1085.             for (; i >= 0; i--) {  
  1086.                 if (value[i] == ch) {  
  1087.                     return i;  
  1088.                 }  
  1089.             }  
  1090.             return -1;  
  1091.         } else {  
  1092.             return lastIndexOfSupplementary(ch, fromIndex);  
  1093.         }  
  1094.     }  
  1095.   
  1096.     /** 
  1097.      * 处理补充字符的最后一次出现索引位置计算 
  1098.      */  
  1099.     private int lastIndexOfSupplementary(int ch, int fromIndex) {  
  1100.         if (Character.isValidCodePoint(ch)) {  
  1101.             final char[] value = this.value;  
  1102.             char hi = Character.highSurrogate(ch);  
  1103.             char lo = Character.lowSurrogate(ch);  
  1104.             int i = Math.min(fromIndex, value.length - 2);  
  1105.             for (; i >= 0; i--) {  
  1106.                 if (value[i] == hi && value[i + 1] == lo) {  
  1107.                     return i;  
  1108.                 }  
  1109.             }  
  1110.         }  
  1111.         return -1;  
  1112.     }  
  1113.   
  1114.     /** 
  1115.      * indexOf方法的重载 
  1116.      */  
  1117.     public int indexOf(String str) {  
  1118.         return indexOf(str, 0);  
  1119.     }  
  1120.   
  1121.     /** 
  1122.      * 返回指定字符串在当前字符串对象中第一次出现的索引位置 
  1123.      */  
  1124.     public int indexOf(String str, int fromIndex) {  
  1125.         return indexOf(value, 0, value.length,  
  1126.                 str.value, 0, str.value.length, fromIndex);  
  1127.     }  
  1128.   
  1129.     /** 
  1130.      * 返回指定目标字符数组的[targetOffset,targetOffset + targetCount]区间内字符序列 
  1131.      * 在源字符数组的[sourceOffset,sourceOffset + sourceCount]区间内字符序列中 
  1132.      * 第一次出现的索引位置 
  1133.      * 
  1134.      * @param   source         待搜索的源字符数组 
  1135.      * @param   sourceOffset   源字符数组搜索的起始偏移量 
  1136.      * @param   sourceCount    源字符数组从起始偏移量位置开始往后搜索的字符个数 
  1137.      * @param   target         待搜索的目标字符数组 
  1138.      * @param   targetOffset   目标字符数组搜索的起始偏移量 
  1139.      * @param   targetCount    目标字符数组从起始偏移量位置开始往后搜索的字符个数 
  1140.      * @param   fromIndex      开始搜索的起始索引位置 
  1141.      */  
  1142.     static int indexOf(char[] source, int sourceOffset, int sourceCount,  
  1143.             char[] target, int targetOffset, int targetCount,  
  1144.             int fromIndex) {  
  1145.         if (fromIndex >= sourceCount) {  
  1146.             return (targetCount == 0 ? sourceCount : -1);  
  1147.         }  
  1148.         if (fromIndex < 0) {  
  1149.             fromIndex = 0;  
  1150.         }  
  1151.         if (targetCount == 0) {  
  1152.             return fromIndex;  
  1153.         }  
  1154.   
  1155.         char first = target[targetOffset];  
  1156.         int max = sourceOffset + (sourceCount - targetCount);  
  1157.   
  1158.         for (int i = sourceOffset + fromIndex; i <= max; i++) {  
  1159.             /* 查找第一个字符 */  
  1160.             if (source[i] != first) {  
  1161.                 while (++i <= max && source[i] != first);  
  1162.             }  
  1163.   
  1164.             if (i <= max) {  
  1165.                 int j = i + 1;  
  1166.                 int end = j + targetCount - 1;  
  1167.                 for (int k = targetOffset + 1; j < end && source[j]  
  1168.                         == target[k]; j++, k++);  
  1169.   
  1170.                 if (j == end) {  
  1171.                     /* 到底目标字符结尾 */  
  1172.                     return i - sourceOffset;  
  1173.                 }  
  1174.             }  
  1175.         }  
  1176.         return -1;  
  1177.     }  
  1178.   
  1179.     /** 
  1180.      * 返回指定字符串在当前字符串对象中的最后一次出现的索引位置 
  1181.      */  
  1182.     public int lastIndexOf(String str) {  
  1183.         return lastIndexOf(str, value.length);  
  1184.     }  
  1185.   
  1186.     /** 
  1187.      * 返回指定字符串在当前字符串对象中的最后一次出现的索引位置, 
  1188.      * 在当前字符串上从指定的fromIndex索引位置开始搜索 
  1189.      */  
  1190.     public int lastIndexOf(String str, int fromIndex) {  
  1191.         return lastIndexOf(value, 0, value.length,  
  1192.                 str.value, 0, str.value.length, fromIndex);  
  1193.     }  
  1194.   
  1195.     /** 
  1196.      * 返回指定目标字符数组的[targetOffset,targetOffset + targetCount]区间内字符序列 
  1197.      * 在源字符数组的[sourceOffset,sourceOffset + sourceCount]区间内字符序列中 
  1198.      * 最后一次出现的索引位置 
  1199.      * 
  1200.      * @param   source         待搜索的源字符数组 
  1201.      * @param   sourceOffset   源字符数组搜索的起始偏移量 
  1202.      * @param   sourceCount    源字符数组从起始偏移量位置开始往后搜索的字符个数 
  1203.      * @param   target         待搜索的目标字符数组 
  1204.      * @param   targetOffset   目标字符数组搜索的起始偏移量 
  1205.      * @param   targetCount    目标字符数组从起始偏移量位置开始往后搜索的字符个数 
  1206.      * @param   fromIndex      开始搜索的起始索引位置 
  1207.      */  
  1208.     static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,  
  1209.             char[] target, int targetOffset, int targetCount,  
  1210.             int fromIndex) {  
  1211.         int rightIndex = sourceCount - targetCount;  
  1212.         if (fromIndex < 0) {  
  1213.             return -1;  
  1214.         }  
  1215.         if (fromIndex > rightIndex) {  
  1216.             fromIndex = rightIndex;  
  1217.         }  
  1218.         /* 若targetCount==0,则直接返回fromIndex */  
  1219.         if (targetCount == 0) {  
  1220.             return fromIndex;  
  1221.         }  
  1222.   
  1223.         int strLastIndex = targetOffset + targetCount - 1;  
  1224.         char strLastChar = target[strLastIndex];  
  1225.         int min = sourceOffset + targetCount - 1;  
  1226.         int i = min + fromIndex;  
  1227.   
  1228.         startSearchForLastChar:  
  1229.         while (true) {  
  1230.             while (i >= min && source[i] != strLastChar) {  
  1231.                 i--;  
  1232.             }  
  1233.             if (i < min) {  
  1234.                 return -1;  
  1235.             }  
  1236.             int j = i - 1;  
  1237.             int start = j - (targetCount - 1);  
  1238.             int k = strLastIndex - 1;  
  1239.   
  1240.             while (j > start) {  
  1241.                 if (source[j--] != target[k--]) {  
  1242.                     i--;  
  1243.                     continue startSearchForLastChar;  
  1244.                 }  
  1245.             }  
  1246.             return start - sourceOffset + 1;  
  1247.         }  
  1248.     }  
  1249.   
  1250.     /** 
  1251.      * 从beginIndex参数表示的索引位置开始截取当前字符串对象 
  1252.      * 若beginIndex=0,则直接返回当前字符串对象,否则截取生成一个子字符串对象 
  1253.      */  
  1254.     public String substring(int beginIndex) {  
  1255.         if (beginIndex < 0) {  
  1256.             throw new StringIndexOutOfBoundsException(beginIndex);  
  1257.         }  
  1258.         int subLen = value.length - beginIndex;  
  1259.         if (subLen < 0) {  
  1260.             throw new StringIndexOutOfBoundsException(subLen);  
  1261.         }  
  1262.         return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);  
  1263.     }  
  1264.   
  1265.     /** 
  1266.      * 截取[beginIndex,endIndex)之间的字符串 
  1267.      * 最终生成的子字符串的长度为endIndex - beginIndex 
  1268.      * 
  1269.      * @param      beginIndex   截取的起始索引位置,包含在内 
  1270.      * @param      endIndex     截取的结束索引位置,不包含在内 
  1271.      * @return     返回截取的子字符串对象 
  1272.      * @exception  IndexOutOfBoundsException  如果 
  1273.      *             beginIndex为负数或 
  1274.      *             endIndex > length()或 
  1275.      *             beginIndex > endIndex,则会抛出索引越界异常 
  1276.      */  
  1277.     public String substring(int beginIndex, int endIndex) {  
  1278.         if (beginIndex < 0) {  
  1279.             throw new StringIndexOutOfBoundsException(beginIndex);  
  1280.         }  
  1281.         if (endIndex > value.length) {  
  1282.             throw new StringIndexOutOfBoundsException(endIndex);  
  1283.         }  
  1284.         int subLen = endIndex - beginIndex;  
  1285.         if (subLen < 0) {  
  1286.             throw new StringIndexOutOfBoundsException(subLen);  
  1287.         }  
  1288.         return ((beginIndex == 0) && (endIndex == value.length)) ? this  
  1289.                 : new String(value, beginIndex, subLen);  
  1290.     }  
  1291.   
  1292.     /** 
  1293.      * 截取[beginIndex,endIndex)之间的字符串,最终生成CharSequence对象 
  1294.      * 与substring(int beginIndex, int endIndex)方法类似,区别就是返回值类型不同 
  1295.      * 
  1296.      * @param      beginIndex   截取的起始索引位置,包含在内 
  1297.      * @param      endIndex     截取的结束索引位置,不包含在内 
  1298.      * @return     返回截取的CharSequence对象 
  1299.      * @exception  IndexOutOfBoundsException  如果 
  1300.      *             beginIndex为负数或 
  1301.      *             endIndex > length()或 
  1302.      *             beginIndex > endIndex,则会抛出索引越界异常 
  1303.      */  
  1304.     public CharSequence subSequence(int beginIndex, int endIndex) {  
  1305.         return this.substring(beginIndex, endIndex);  
  1306.     }  
  1307.   
  1308.     /** 
  1309.      * 将指定的字符串拼接到当前字符串的末尾 
  1310.      * 若str参数表示的字符串的长度==0,那么直接返回this,否则会创建一个新的字符串对象,比如: 
  1311.      * "cares".concat("s") returns "caress" 
  1312.      * "to".concat("get").concat("her") returns "together" 
  1313.      * 
  1314.      * @param   str   需要拼接到当前字符串末尾的字符串对象 
  1315.      * @return  返回拼接后的字符串对象 
  1316.      */  
  1317.     public String concat(String str) {  
  1318.         int otherLen = str.length();  
  1319.         if (otherLen == 0) {  
  1320.             return this;  
  1321.         }  
  1322.         int len = value.length;  
  1323.         char buf[] = Arrays.copyOf(value, len + otherLen);  
  1324.         str.getChars(buf, len);  
  1325.         return new String(buf, true);  
  1326.     }  
  1327.   
  1328.     /** 
  1329.      * 替换当前字符串对象中所有出现的oldChar字符为newChar字符,最终 
  1330.      * 返回一个新的字符串对象 
  1331.      * 若当前字符串对象中不包含oldChar字符,那么直接return this,否则, 
  1332.      * 会生成一个新的字符串对象并返回 
  1333.      * 示例: 
  1334.      * "mesquite in your cellar".replace('e', 'o') 
  1335.      *         returns "mosquito in your collar" 
  1336.      * "the war of baronets".replace('r', 'y') 
  1337.      *         returns "the way of bayonets" 
  1338.      * "sparring with a purple porpoise".replace('p', 't') 
  1339.      *         returns "starring with a turtle tortoise" 
  1340.      * "JonL".replace('q', 'x') 
  1341.      *         returns "JonL" (无变化) 
  1342.      * @param   oldChar   被替换的旧字符 
  1343.      * @param   newChar   替换的新字符 
  1344.      * @return  返回替换指定字符后新的字符串对象 
  1345.      */  
  1346.     public String replace(char oldChar, char newChar) {  
  1347.         //若被替换字符与替换字符不相等才会执行下面的操作,否则直接return this.  
  1348.         if (oldChar != newChar) {  
  1349.             int len = value.length;  
  1350.             int i = -1;  
  1351.             char[] val = value; /* 避免直接操作value属性 */  
  1352.   
  1353.             //从索引位置零开始查找当前字符串中第一次出现字符oldChar的索引位置  
  1354.             while (++i < len) {  
  1355.                 if (val[i] == oldChar) {  
  1356.                     break;  
  1357.                 }  
  1358.             }  
  1359.             // 若查找到oldChar在当前字符串中第一次出现的索引位置 < length(),  
  1360.             // 否则就没有字符替换的意义了  
  1361.             if (i < len) {  
  1362.                 //将[0,i)直接的字符缓存到char[]字符数组中  
  1363.                 char buf[] = new char[len];  
  1364.                 for (int j = 0; j < i; j++) {  
  1365.                     buf[j] = val[j];  
  1366.                 }  
  1367.                 //遍历[i,length() - 1]之间的字符  
  1368.                 while (i < len) {  
  1369.                     //获取遍历到的每个字符  
  1370.                     char c = val[i];  
  1371.                     // 若当前遍历到的字符与oldChar相等,则把当前遍历到的字符替换为newChar,  
  1372.                     // 否则当前遍历到的字符保持不变,然后将其存入char[]字符数组中  
  1373.                     buf[i] = (c == oldChar) ? newChar : c;  
  1374.                     i++;  
  1375.                 }  
  1376.                 // 最终根据临时变量char[]字符数组构造一个新的字符串对象并返回  
  1377.                 return new String(buf, true);  
  1378.             }  
  1379.         }  
  1380.         return this;  
  1381.     }  
  1382.   
  1383.     /** 
  1384.      * 检测当前字符串是否符合给定的正则表达式 
  1385.      * 
  1386.      * @param   regex    当前字符串对象用来匹配的正则表达式 
  1387.      * @return  当且仅当当前字符串匹配给定的正则表达式才会返回true 
  1388.      * @throws  PatternSyntaxException 
  1389.      *          若给定的正则表达式语法错误会抛出此异常 
  1390.      * 
  1391.      * @see java.util.regex.Pattern 
  1392.      * 
  1393.      * @since 1.4 
  1394.      * @spec JSR-51 
  1395.      */  
  1396.     public boolean matches(String regex) {  
  1397.         return Pattern.matches(regex, this);  
  1398.     }  
  1399.   
  1400.     /** 
  1401.      * 当且仅当当前字符串包含指定的字符序列才会返回true 
  1402.      * Returns true if and only if this string contains the specified 
  1403.      * sequence of char values. 
  1404.      * 
  1405.      * @param s    给定的字符序列对象 
  1406.      * @return true  若当前字符串包含给定的参数s表示的字符序列时返回true 
  1407.      * @throws NullPointerException 若参数s表示的字符串对象为null,则会抛出NullPointerException异常 
  1408.      * @since 1.5 
  1409.      */  
  1410.     public boolean contains(CharSequence s) {  
  1411.         return indexOf(s.toString()) > -1;  
  1412.     }  
  1413.   
  1414.     /** 
  1415.      * 根据给定的正则表达式替换当前字符串匹配到的第一个子字符串为参数replacement表示的字符串 
  1416.      * 注意:replacement参数中若包含反斜杠\和美元符号$可能会与直接将其当做纯文本替换字符串 
  1417.      * 返回的结果不一致.如果你需要抑制特殊字符的潜在含义,那么你可能会需要使用 
  1418.      * java.util.regex.Matcher类的quoteReplacement方法来实现当前方法的功能。默认情况下, 
  1419.      * 当前方法是采用java.util.regex.Matcher类的replaceFirst方法实现的. 
  1420.      * 
  1421.      * @param   regex         给定的正则表达式 
  1422.      * @param   replacement   替换字符串 
  1423.      * @return  String 
  1424.      * @throws  PatternSyntaxException 
  1425.      *          若给定的正则表达式语法错误会抛出此异常 
  1426.      * 
  1427.      * @see java.util.regex.Pattern 
  1428.      * 
  1429.      * @since 1.4 
  1430.      * @spec JSR-51 
  1431.      */  
  1432.     public String replaceFirst(String regex, String replacement) {  
  1433.         return Pattern.compile(regex).matcher(this).replaceFirst(replacement);  
  1434.     }  
  1435.   
  1436.     /** 
  1437.      * 根据给定的正则表达式替换当前字符串匹配到的所有子字符串为参数replacement表示的字符串 
  1438.      * 注意:replacement参数中若包含反斜杠\和美元符号$可能会与直接将其当做纯文本替换字符串 
  1439.      * 返回的结果不一致.如果你需要抑制特殊字符的潜在含义,那么你可能会需要使用 
  1440.      * java.util.regex.Matcher类的quoteReplacement方法来实现当前方法的功能。默认情况下, 
  1441.      * 当前方法是采用java.util.regex.Matcher类的replaceAll方法实现的. 
  1442.      * 
  1443.      * @param   regex         给定的正则表达式 
  1444.      * @param   replacement   替换字符串 
  1445.      * @return  String 
  1446.      * @throws  PatternSyntaxException 
  1447.      *          若给定的正则表达式语法错误会抛出此异常 
  1448.      * 
  1449.      * @see java.util.regex.Pattern 
  1450.      * 
  1451.      * @since 1.4 
  1452.      * @spec JSR-51 
  1453.      */  
  1454.     public String replaceAll(String regex, String replacement) {  
  1455.         return Pattern.compile(regex).matcher(this).replaceAll(replacement);  
  1456.     }  
  1457.   
  1458.     /** 
  1459.      * 将当前字符串中第一次出现的target字符序列替换为replacement字符序列 
  1460.      * 注意:若target或replacement参数中包含了正则表达式中的特殊字符,会一律 
  1461.      * 按照纯文本字符去理解,不会被理解为它在正则表达式中表达的含义, 
  1462.      * 即当前方法不支持正则表达式. 
  1463.      * @param  target         被替换的字符序列 
  1464.      * @param  replacement    替换的字符序列 
  1465.      * @return  The resulting string 
  1466.      * @throws NullPointerException if <code>target</code> or 
  1467.      *         <code>replacement</code> is <code>null</code>. 
  1468.      * @since 1.5 
  1469.      */  
  1470.     public String replace(CharSequence target, CharSequence replacement) {  
  1471.         return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(  
  1472.                 this).replaceAll(Matcher.quoteReplacement(replacement.toString()));  
  1473.     }  
  1474.   
  1475.     /** 
  1476.      * 根据给定的正则表达式来分割当前字符串并返回一个字符串数组 
  1477.      * 如果给定的正则表达式不匹配当前字符串,那么返回的字符串数组将只包含一个元素即 
  1478.      * 当前字符串对象.返回的字符串数组中的每个子字符串与它们在当前字符串中出现的顺序 
  1479.      * 保持一致. 
  1480.      * limit参数用于控制给定的正则表达式应用的次数,从而影响最终返回的字符串数组的长度. 
  1481.      * 若limit参数大于零,那么给定的正则表达式则会至多应用limit - 1次,同时最终返回的 
  1482.      * 字符串数组的长度将不大于limit,并且该数组的最后一个元素为前一个子字符串匹配后剩余 
  1483.      * 的部分。比如: 
  1484.      * "Hello world, Java"  -->  split(" ",2); 
  1485.      *         return: "Hello"  "world, Java" 
  1486.      * 若limit参数是一个负数,那么给定的正则表达式将会尽可能多的应用多次并且返回的字符串 
  1487.      * 数组的长度将会没有限制. 
  1488.      * 若limit参数为零,那么给定的正则表达式将会尽可能多的应用多次并且返回的字符串 
  1489.      * 数组的长度将会没有限制,尾部的空字符串将会被丢弃. 
  1490.      * 
  1491.      * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the 
  1492.      * following results with these parameters: 
  1493.      * 
  1494.      * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result"> 
  1495.      * <tr> 
  1496.      *     <th>Regex</th> 
  1497.      *     <th>Limit</th> 
  1498.      *     <th>Result</th> 
  1499.      * </tr> 
  1500.      * <tr><td align=center>:</td> 
  1501.      *     <td align=center>2</td> 
  1502.      *     <td><tt>{ "boo", "and:foo" }</tt></td></tr> 
  1503.      * <tr><td align=center>:</td> 
  1504.      *     <td align=center>5</td> 
  1505.      *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr> 
  1506.      * <tr><td align=center>:</td> 
  1507.      *     <td align=center>-2</td> 
  1508.      *     <td><tt>{ "boo", "and", "foo" }</tt></td></tr> 
  1509.      * <tr><td align=center>o</td> 
  1510.      *     <td align=center>5</td> 
  1511.      *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> 
  1512.      * <tr><td align=center>o</td> 
  1513.      *     <td align=center>-2</td> 
  1514.      *     <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr> 
  1515.      * <tr><td align=center>o</td> 
  1516.      *     <td align=center>0</td> 
  1517.      *     <td><tt>{ "b", "", ":and:f" }</tt></td></tr> 
  1518.      * </table></blockquote> 
  1519.      * 
  1520.      * <blockquote> 
  1521.      * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile 
  1522.      * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link 
  1523.      * java.util.regex.Pattern#split(java.lang.CharSequence,int) 
  1524.      * split}<tt>(</tt><i>str</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt> 
  1525.      * </blockquote> 
  1526.      * 
  1527.      * @param  regex  表示分隔符的正则表达式 
  1528.      * @param  limit  限制返回的字符串数组长度的阈值 
  1529.      * @return  返回当前字符串被分割后生成的字符串数组 
  1530.      * @throws  PatternSyntaxException 
  1531.      *          若给定的正则表达式语法错误会抛出此异常 
  1532.      * 
  1533.      * @see java.util.regex.Pattern 
  1534.      * 
  1535.      * @since 1.4 
  1536.      * @spec JSR-51 
  1537.      */  
  1538.     public String[] split(String regex, int limit) {  
  1539.         /** 
  1540.          * 分3种情况处理: 
  1541.          * 1. regex参数只有一个字符且该字符串不是正则表达式中的特殊字符 .$|()[{^?*+\ 或者 
  1542.          * 2. regex参数为2个字符,第一个字符是一个反斜杠\,第二个字符为非ASCII码字母或非ASCII码数字 
  1543.          * 3. regex参数超过2个字符并且为合法的正则表达式 
  1544.          * 前2种情况采用fastpath方式进行处理,后面第3种情况采用Pattern.split(this, limit)方法实现 
  1545.          */  
  1546.         char ch = 0;  
  1547.         //判定regex参数是否为上面所描述的前两种情况  
  1548.         if (((regex.value.length == 1 &&  
  1549.              ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||  
  1550.              (regex.length() == 2 &&  
  1551.               regex.charAt(0) == '\\' &&  
  1552.               (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&  
  1553.               ((ch-'a')|('z'-ch)) < 0 &&  
  1554.               ((ch-'A')|('Z'-ch)) < 0)) &&  
  1555.             (ch < Character.MIN_HIGH_SURROGATE ||  
  1556.              ch > Character.MAX_LOW_SURROGATE))  
  1557.         {  
  1558.             int off = 0;  
  1559.             int next = 0;  
  1560.             boolean limited = limit > 0;  
  1561.             ArrayList<String> list = new ArrayList<>();  
  1562.             while ((next = indexOf(ch, off)) != -1) {  
  1563.                 if (!limited || list.size() < limit - 1) {  
  1564.                     //截取每一段子字符串存入list中  
  1565.                     list.add(substring(off, next));  
  1566.                     //修改截取的起始索引位置  
  1567.                     off = next + 1;  
  1568.                 } else {  
  1569.                     //最后一个,只有设置的limit参数大于零,才会进入这个分支  
  1570.                     list.add(substring(off, value.length));  
  1571.                     off = value.length;  
  1572.                     break;  
  1573.                 }  
  1574.             }  
  1575.             // off为零,当前字符串与给定的regex参数不匹配,那么直接返回一个字符串数组  
  1576.             // 并且该字符串数组只包含一个元素且该元素为当前字符串对象  
  1577.             if (off == 0)  
  1578.                 return new String[]{this};  
  1579.   
  1580.             // 添加剩余的部分  
  1581.             if (!limited || list.size() < limit) {  
  1582.                 list.add(substring(off, value.length));  
  1583.             }  
  1584.   
  1585.             // 构造最终的返回结果  
  1586.             int resultSize = list.size();  
  1587.             //若limit参数设置为零  
  1588.             if (limit == 0) {  
  1589.                 //从尾部开始遍历,排除尾部连续的空字符串  
  1590.                 while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {  
  1591.                     resultSize--;  
  1592.                 }  
  1593.             }  
  1594.             String[] result = new String[resultSize];  
  1595.             //这里使用了list.subList方法,而该方法返回的SubList对象会在内部维护当前List对象,  
  1596.             //对SubList对象中的元素的操作会直接反映到其内部维护的List对象中,若SubList对象没有  
  1597.             //被回收,那么内部维护的List对象也不会被回收,内部维护的List中保存的对象也不会被回收,  
  1598.             //若内部维护的List是一个超大的集合,那么就会很容易发生OOM异常  
  1599.             //应该通过new ArrayList(list.subList(0, resultSize).toArray(result));  
  1600.             //这种方式来解决这种隐患  
  1601.             return list.subList(0, resultSize).toArray(result);  
  1602.         }  
  1603.         // 若regex参数超过2个字符并且是合法的正则表达式,那么直接调用Pattern类的.split(this, limit)  
  1604.         // 来完成实现  
  1605.         return Pattern.compile(regex).split(this, limit);  
  1606.     }  
  1607.   
  1608.     /** 
  1609.      * split(String regex, int limit)方法的重载,limit参数默认值为零 
  1610.      * 
  1611.      * @since 1.4 
  1612.      * @spec JSR-51 
  1613.      */  
  1614.     public String[] split(String regex) {  
  1615.         return split(regex, 0);  
  1616.     }  
  1617.   
  1618.     /** 
  1619.      * 使用给定Local的大小写形式的转换规则将当前字符串对象的字符序列中包含的每个字符转换成小写形式 
  1620.      * 由于大小写映射并不总是以1:1的形式进行字符映射,因此可能会导致转换后的字符串长度与原字符串的长度 
  1621.      * 不一致. 
  1622.      * 
  1623.      * Examples of lowercase  mappings are in the following table: 
  1624.      * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description"> 
  1625.      * <tr> 
  1626.      *   <th>Language Code of Locale</th> 
  1627.      *   <th>Upper Case</th> 
  1628.      *   <th>Lower Case</th> 
  1629.      *   <th>Description</th> 
  1630.      * </tr> 
  1631.      * <tr> 
  1632.      *   <td>tr (Turkish)</td> 
  1633.      *   <td>&#92;u0130</td> 
  1634.      *   <td>&#92;u0069</td> 
  1635.      *   <td>capital letter I with dot above -&gt; small letter i</td> 
  1636.      * </tr> 
  1637.      * <tr> 
  1638.      *   <td>tr (Turkish)</td> 
  1639.      *   <td>&#92;u0049</td> 
  1640.      *   <td>&#92;u0131</td> 
  1641.      *   <td>capital letter I -&gt; small letter dotless i </td> 
  1642.      * </tr> 
  1643.      * <tr> 
  1644.      *   <td>(all)</td> 
  1645.      *   <td>French Fries</td> 
  1646.      *   <td>french fries</td> 
  1647.      *   <td>lowercased all chars in String</td> 
  1648.      * </tr> 
  1649.      * <tr> 
  1650.      *   <td>(all)</td> 
  1651.      *   <td><img src="doc-files/capiota.gif" alt="capiota"><img src="doc-files/capchi.gif" alt="capchi"> 
  1652.      *       <img src="doc-files/captheta.gif" alt="captheta"><img src="doc-files/capupsil.gif" alt="capupsil"> 
  1653.      *       <img src="doc-files/capsigma.gif" alt="capsigma"></td> 
  1654.      *   <td><img src="doc-files/iota.gif" alt="iota"><img src="doc-files/chi.gif" alt="chi"> 
  1655.      *       <img src="doc-files/theta.gif" alt="theta"><img src="doc-files/upsilon.gif" alt="upsilon"> 
  1656.      *       <img src="doc-files/sigma1.gif" alt="sigma"></td> 
  1657.      *   <td>lowercased all chars in String</td> 
  1658.      * </tr> 
  1659.      * </table> 
  1660.      * 
  1661.      * @param locale  语言环境对象,不同的语言环境下的大小写字符转换规则不同 
  1662.      * @return  返回当前字符串对象的小写形式 
  1663.      * @see     java.lang.String#toLowerCase() 
  1664.      * @see     java.lang.String#toUpperCase() 
  1665.      * @see     java.lang.String#toUpperCase(Locale) 
  1666.      * @since   1.1 
  1667.      */  
  1668.     public String toLowerCase(Locale locale) {  
  1669.         //若locale参数为null,则直接抛出NullPointerException异常  
  1670.         if (locale == null) {  
  1671.             throw new NullPointerException();  
  1672.         }  
  1673.   
  1674.         int firstUpper;  
  1675.         final int len = value.length;  
  1676.   
  1677.         //先扫描出前面本身已经是小写形式的字符  
  1678.         scan: {  
  1679.             for (firstUpper = 0 ; firstUpper < len; ) {  
  1680.                 char c = value[firstUpper];  
  1681.                 //若当前字符在High Surrogate的字符范围内  
  1682.                 if ((c >= Character.MIN_HIGH_SURROGATE)  
  1683.                         && (c <= Character.MAX_HIGH_SURROGATE)) {  
  1684.                     int supplChar = codePointAt(firstUpper);  
  1685.                     if (supplChar != Character.toLowerCase(supplChar)) {  
  1686.                         break scan;  
  1687.                     }  
  1688.                     //通过Character.charCount计算实际字符的个数  
  1689.                     firstUpper += Character.charCount(supplChar);  
  1690.                 } else {  
  1691.                     if (c != Character.toLowerCase(c)) {  
  1692.                         break scan;  
  1693.                     }  
  1694.                     firstUpper++;  
  1695.                 }  
  1696.             }  
  1697.             return this;  
  1698.         }  
  1699.   
  1700.         char[] result = new char[len];  
  1701.         int resultOffset = 0;  
  1702.   
  1703.         /* 复制第一个小写字符 */  
  1704.         System.arraycopy(value, 0, result, 0, firstUpper);  
  1705.   
  1706.         String lang = locale.getLanguage();  
  1707.         boolean localeDependent =  
  1708.                 (lang == "tr" || lang == "az" || lang == "lt");  
  1709.         char[] lowerCharArray;  
  1710.         int lowerChar;  
  1711.         int srcChar;  
  1712.         int srcCount;  
  1713.         //从firstUpper索引位置开始,后面的字符都是需要进行小写处理的  
  1714.         for (int i = firstUpper; i < len; i += srcCount) {  
  1715.             srcChar = (int)value[i];  
  1716.             //若当前字符是HIGH SURROGATE  
  1717.             if ((char)srcChar >= Character.MIN_HIGH_SURROGATE  
  1718.                     && (char)srcChar <= Character.MAX_HIGH_SURROGATE) {  
  1719.                 //获取实际的Unicode代码点  
  1720.                 srcChar = codePointAt(i);  
  1721.                 //计算实际字符长度  
  1722.                 srcCount = Character.charCount(srcChar);  
  1723.             } else {  
  1724.                 srcCount = 1;  
  1725.             }  
  1726.             //考虑特殊情况  
  1727.             if (localeDependent ||  
  1728.                 srcChar == '\u03A3' || // 希腊大写字母σ  
  1729.                 srcChar == '\u0130') { // 拉丁大写字母I  
  1730.                 lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);  
  1731.             } else {  
  1732.                 //一般情况,直接Character.toLowerCase()方式转换成小写  
  1733.                 lowerChar = Character.toLowerCase(srcChar);  
  1734.             }  
  1735.             //若转换后得到的是错误字符,或者是一个Unicode补充代码点  
  1736.             if ((lowerChar == Character.ERROR)  
  1737.                     || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {  
  1738.                 if (lowerChar == Character.ERROR) {  
  1739.                     lowerCharArray =  
  1740.                             ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);  
  1741.                 } else if (srcCount == 2) {  
  1742.                     resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;  
  1743.                     continue;  
  1744.                 } else {  
  1745.                     lowerCharArray = Character.toChars(lowerChar);  
  1746.                 }  
  1747.   
  1748.                 //得到最终小写字符数组的长度  
  1749.                 int mapLen = lowerCharArray.length;  
  1750.                 //如果大于原字符串长度  
  1751.                 if (mapLen > srcCount) {  
  1752.                     //小写字符数组扩容  
  1753.                     char[] result2 = new char[result.length + mapLen - srcCount];  
  1754.                     //result --> result2  
  1755.                     System.arraycopy(result, 0, result2, 0, i + resultOffset);  
  1756.                     result = result2;  
  1757.                 }  
  1758.                 for (int x = 0; x < mapLen; ++x) {  
  1759.                     result[i + resultOffset + x] = lowerCharArray[x];  
  1760.                 }  
  1761.                 resultOffset += (mapLen - srcCount);  
  1762.             } else {  
  1763.                 result[i + resultOffset] = (char)lowerChar;  
  1764.             }  
  1765.         }  
  1766.         return new String(result, 0, len + resultOffset);  
  1767.     }  
  1768.   
  1769.     /** 
  1770.      * toLowerCase(Locale locale)方法的重载, 
  1771.      * Local默认值为Locale.getDefault(),默认的Local跟你 
  1772.      * 当前JVM实例运行的主机系统平台环境有关 
  1773.      * @see     java.lang.String#toLowerCase(Locale) 
  1774.      */  
  1775.     public String toLowerCase() {  
  1776.         return toLowerCase(Locale.getDefault());  
  1777.     }  
  1778.   
  1779.     /** 
  1780.      * 使用给定Local的大小写形式的转换规则将当前字符串对象的字符序列中包含的每个字符转换成大写形式 
  1781.      * 由于大小写映射并不总是以1:1的形式进行字符映射,因此可能会导致转换后的字符串长度与原字符串的长度 
  1782.      * 不一致. 
  1783.      * @param locale  语言环境对象,不同的语言环境下的大小写字符转换规则不同 
  1784.      * @return  返回当前字符串对象的大写形式 
  1785.      * @see     java.lang.String#toUpperCase() 
  1786.      * @see     java.lang.String#toLowerCase() 
  1787.      * @see     java.lang.String#toLowerCase(Locale) 
  1788.      * @since   1.1 
  1789.      */  
  1790.     public String toUpperCase(Locale locale) {  
  1791.         if (locale == null) {  
  1792.             throw new NullPointerException();  
  1793.         }  
  1794.   
  1795.         int firstLower;  
  1796.         final int len = value.length;  
  1797.   
  1798.         scan: {  
  1799.            for (firstLower = 0 ; firstLower < len; ) {  
  1800.                 int c = (int)value[firstLower];  
  1801.                 int srcCount;  
  1802.                 if ((c >= Character.MIN_HIGH_SURROGATE)  
  1803.                         && (c <= Character.MAX_HIGH_SURROGATE)) {  
  1804.                     c = codePointAt(firstLower);  
  1805.                     srcCount = Character.charCount(c);  
  1806.                 } else {  
  1807.                     srcCount = 1;  
  1808.                 }  
  1809.                 int upperCaseChar = Character.toUpperCaseEx(c);  
  1810.                 if ((upperCaseChar == Character.ERROR)  
  1811.                         || (c != upperCaseChar)) {  
  1812.                     break scan;  
  1813.                 }  
  1814.                 firstLower += srcCount;  
  1815.             }  
  1816.             return this;  
  1817.         }  
  1818.   
  1819.         char[] result = new char[len]; /* may grow */  
  1820.         int resultOffset = 0;  /* result may grow, so i+resultOffset 
  1821.          * is the write location in result */  
  1822.   
  1823.         /* Just copy the first few upperCase characters. */  
  1824.         System.arraycopy(value, 0, result, 0, firstLower);  
  1825.   
  1826.         String lang = locale.getLanguage();  
  1827.         boolean localeDependent =  
  1828.                 (lang == "tr" || lang == "az" || lang == "lt");  
  1829.         char[] upperCharArray;  
  1830.         int upperChar;  
  1831.         int srcChar;  
  1832.         int srcCount;  
  1833.         for (int i = firstLower; i < len; i += srcCount) {  
  1834.             srcChar = (int)value[i];  
  1835.             if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&  
  1836.                 (char)srcChar <= Character.MAX_HIGH_SURROGATE) {  
  1837.                 srcChar = codePointAt(i);  
  1838.                 srcCount = Character.charCount(srcChar);  
  1839.             } else {  
  1840.                 srcCount = 1;  
  1841.             }  
  1842.             if (localeDependent) {  
  1843.                 upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);  
  1844.             } else {  
  1845.                 upperChar = Character.toUpperCaseEx(srcChar);  
  1846.             }  
  1847.             if ((upperChar == Character.ERROR)  
  1848.                     || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {  
  1849.                 if (upperChar == Character.ERROR) {  
  1850.                     if (localeDependent) {  
  1851.                         upperCharArray =  
  1852.                                 ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);  
  1853.                     } else {  
  1854.                         upperCharArray = Character.toUpperCaseCharArray(srcChar);  
  1855.                     }  
  1856.                 } else if (srcCount == 2) {  
  1857.                     resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;  
  1858.                     continue;  
  1859.                 } else {  
  1860.                     upperCharArray = Character.toChars(upperChar);  
  1861.                 }  
  1862.   
  1863.                 /* Grow result if needed */  
  1864.                 int mapLen = upperCharArray.length;  
  1865.                 if (mapLen > srcCount) {  
  1866.                     char[] result2 = new char[result.length + mapLen - srcCount];  
  1867.                     System.arraycopy(result, 0, result2, 0, i + resultOffset);  
  1868.                     result = result2;  
  1869.                 }  
  1870.                 for (int x = 0; x < mapLen; ++x) {  
  1871.                     result[i + resultOffset + x] = upperCharArray[x];  
  1872.                 }  
  1873.                 resultOffset += (mapLen - srcCount);  
  1874.             } else {  
  1875.                 result[i + resultOffset] = (char)upperChar;  
  1876.             }  
  1877.         }  
  1878.         return new String(result, 0, len + resultOffset);  
  1879.     }  
  1880.   
  1881.     /** 
  1882.      * toUpperCase(Locale locale)方法的重载,Local参数默认值为Locale.getDefault(), 
  1883.      * 默认的Local跟你当前JVM实例运行的主机系统平台环境有关 
  1884.      * @see     java.lang.String#toUpperCase(Locale) 
  1885.      */  
  1886.     public String toUpperCase() {  
  1887.         return toUpperCase(Locale.getDefault());  
  1888.     }  
  1889.   
  1890.     /** 
  1891.      * 剔除掉当前字符串对象的两头连续的空格字符,并返回一个新的字符串对象 
  1892.      * 
  1893.      * @return  返回剔除掉两头空格后的字符串对象 
  1894.      */  
  1895.     public String trim() {  
  1896.         int len = value.length;  
  1897.         int st = 0;  
  1898.         char[] val = value;  
  1899.   
  1900.         //从开头开始找空格字符  
  1901.         while ((st < len) && (val[st] <= ' ')) {  
  1902.             st++;  
  1903.         }  
  1904.         //从末尾往开头找空格字符  
  1905.         while ((st < len) && (val[len - 1] <= ' ')) {  
  1906.             len--;  
  1907.         }  
  1908.         //若没找到空格字符,则直接返回当前字符串对象,否则截取字符串并返回  
  1909.         return ((st > 0) || (len < value.length)) ? substring(st, len) : this;  
  1910.     }  
  1911.   
  1912.     /** 
  1913.      * 因为当前字符串对象已经是String类型,因此这里直接return this. 
  1914.      * 
  1915.      * @return  the string itself. 
  1916.      */  
  1917.     public String toString() {  
  1918.         return this;  
  1919.     }  
  1920.   
  1921.     /** 
  1922.      * 将当前字符串对象转换成一个字符数组 
  1923.      * 
  1924.      * @return  返回当前字符串对象转换后得到的一个字符数组,该字符数组的长度与 
  1925.      *          当前字符串的长度一致 
  1926.      */  
  1927.     public char[] toCharArray() {  
  1928.         // 由于类初始化问题,这里不能使用Arrays.copyOf()方法来实现  
  1929.         char result[] = new char[value.length];  
  1930.         System.arraycopy(value, 0, result, 0, value.length);  
  1931.         return result;  
  1932.     }  
  1933.   
  1934.     /** 
  1935.      * 使用指定的字符串格式和参数返回一个格式化后的字符串 
  1936.      * 
  1937.      * @param  format  字符串格式参数 
  1938.      * 
  1939.      * @param  args    字符串格式中需要替换的参数 
  1940.      * 
  1941.      * //@throws  IllegalFormatException 
  1942.      *          如果给定的字符串格式不合法或者给定的字符串格式与指定的参数不兼容, 
  1943.      *          或者给定的字符串格式需要的参数个数大于实际指定的参数个数,则会抛出 
  1944.      *          IllegalFormatException异常 
  1945.      * 
  1946.      * @throws  NullPointerException 
  1947.      *          如果format参数等于null,则会抛出NullPointerException异常 
  1948.      * 
  1949.      * @return  返回格式化后的字符串 
  1950.      * 
  1951.      * @see  java.util.Formatter 
  1952.      * @since  1.5 
  1953.      */  
  1954.     public static String format(String format, Object... args) {  
  1955.         return new Formatter().format(format, args).toString();  
  1956.     }  
  1957.   
  1958.     /** 
  1959.      * 使用指定的字符串格式和参数在指定的语言环境下返回一个格式化后的字符串 
  1960.      * 
  1961.      * @param  l        本地语言环境 
  1962.      * @param  format   字符串格式 
  1963.      * @param  args     字符串格式中需要替换的参数 
  1964.      * 
  1965.      * //@throws  IllegalFormatException 
  1966.      *          如果给定的字符串格式不合法或者给定的字符串格式与指定的参数不兼容, 
  1967.      *          或者给定的字符串格式需要的参数个数大于实际指定的参数个数,则会抛出 
  1968.      *          IllegalFormatException异常 
  1969.      * 
  1970.      * @throws  NullPointerException 
  1971.      *          如果format参数等于null,则会抛出NullPointerException异常 
  1972.      * 
  1973.      * @return  返回格式化后的字符串 
  1974.      * 
  1975.      * @see  java.util.Formatter 
  1976.      * @since  1.5 
  1977.      */  
  1978.     public static String format(Locale l, String format, Object... args) {  
  1979.         return new Formatter(l).format(format, args).toString();  
  1980.     }  
  1981.   
  1982.     /** 
  1983.      * 将指定的obj对象转换成String对象 
  1984.      * 
  1985.      * @param   obj   任意的Object对象 
  1986.      * @return  若obj == null,则会返回字符串"null",否则返回obj.toString() 
  1987.      * @see     java.lang.Object#toString() 
  1988.      */  
  1989.     public static String valueOf(Object obj) {  
  1990.         return (obj == null) ? "null" : obj.toString();  
  1991.     }  
  1992.   
  1993.     /** 
  1994.      * 将指定的字符数组对象转换成String对象 
  1995.      * 
  1996.      * @param   data   字符数组对象 
  1997.      * @return  返回一个新的字符串对象 
  1998.      */  
  1999.     public static String valueOf(char data[]) {  
  2000.         return new String(data);  
  2001.     }  
  2002.   
  2003.     /** 
  2004.      * 将指定的字符数组的[offset,offset + count]区间内的字符序列转换成一个字符串对象 
  2005.      * 
  2006.      * @param   data     字符数组 
  2007.      * @param   offset   截取的起始偏移量 
  2008.      * @param   count    截取的字符个数 
  2009.      * @return  返回一个包含给定字符数组指定区间内的字符序列的字符串对象 
  2010.      * @exception IndexOutOfBoundsException 
  2011.      *            若offset为负数或 
  2012.      *            count为负数或 
  2013.      *            offset + count > data.length(), 
  2014.      *            则会抛出IndexOutOfBoundsException数组索引位置越界异常 
  2015.      */  
  2016.     public static String valueOf(char data[], int offset, int count) {  
  2017.         return new String(data, offset, count);  
  2018.     }  
  2019.   
  2020.     /** 
  2021.      * 将指定的字符数组的[offset,offset + count]区间内的字符序列转换成一个字符串对象 
  2022.      * 同valueOf(char data[], int offset, int count)方法实现细节一模一样,仅仅只是方法名称不同 
  2023.      */  
  2024.     public static String copyValueOf(char data[], int offset, int count) {  
  2025.         return new String(data, offset, count);  
  2026.     }  
  2027.   
  2028.     /** 
  2029.      * 将指定的字符数组转换成一个字符串对象 
  2030.      * 同valueOf(char data[])方法的具体实现细节一模一样,仅仅只是方法名称不同 
  2031.      * 
  2032.      * @param   data   字符数组对象 
  2033.      * @return  返回一个新的字符串对象 
  2034.      */  
  2035.     public static String copyValueOf(char data[]) {  
  2036.         return new String(data);  
  2037.     }  
  2038.   
  2039.     /** 
  2040.      * 将boolean变量值转换成一个字符串对象 
  2041.      * 
  2042.      * @param   b   一个boolean值 
  2043.      * @return  true   --> "true" 
  2044.      *          false  --> "false" 
  2045.      */  
  2046.     public static String valueOf(boolean b) {  
  2047.         return b ? "true" : "false";  
  2048.     }  
  2049.   
  2050.     /** 
  2051.      * 将单个字符转换成一个字符串对象 
  2052.      * 
  2053.      * @param   c   一个字符 
  2054.      * @return  返回单个字符转换后得到的一个长度为1的字符串对象 
  2055.      */  
  2056.     public static String valueOf(char c) {  
  2057.         char data[] = {c};  
  2058.         return new String(data, true);  
  2059.     }  
  2060.   
  2061.     /** 
  2062.      * 将int数字转换成一个字符串对象 
  2063.      * 内部实际是调用Integer.toString()方法实现的 
  2064.      * 
  2065.      * @param   i   int数字 
  2066.      * @return  返回一个int类型的数字的字符串表示形式 
  2067.      * @see     java.lang.Integer#toString(int, int) 
  2068.      */  
  2069.     public static String valueOf(int i) {  
  2070.         return Integer.toString(i);  
  2071.     }  
  2072.   
  2073.     /** 
  2074.      * 将long数字转换成一个字符串对象 
  2075.      * 内部实际是调用Long.toString()方法实现的 
  2076.      * 
  2077.      * @param   l   long类型的数字 
  2078.      * @return  返回一个long类型的数字的字符串表示形式 
  2079.      * @see     java.lang.Long#toString(long) 
  2080.      */  
  2081.     public static String valueOf(long l) {  
  2082.         return Long.toString(l);  
  2083.     }  
  2084.   
  2085.     /** 
  2086.      * 将float数字转换成一个字符串对象 
  2087.      * 内部实际是调用Float.toString()方法实现的 
  2088.      * 
  2089.      * @param   f   float类型的数字 
  2090.      * @return  返回一个float类型的数字的字符串表示形式 
  2091.      * @see     java.lang.Float#toString(float) 
  2092.      */  
  2093.     public static String valueOf(float f) {  
  2094.         return Float.toString(f);  
  2095.     }  
  2096.   
  2097.     /** 
  2098.      * 将double数字转换成一个字符串对象 
  2099.      * 内部实际是调用Double.toString()方法实现的 
  2100.      * 
  2101.      * @param   d   double类型的数字 
  2102.      * @return  返回一个double类型的数字的字符串表示形式 
  2103.      * @see     java.lang.Double#toString(double) 
  2104.      */  
  2105.     public static String valueOf(double d) {  
  2106.         return Double.toString(d);  
  2107.     }  
  2108.   
  2109.     /** 
  2110.      * 返回字符串对象的规范化表示形式 
  2111.      * 字符串常量池初始化默认是空的,它由String类私下管理维护 
  2112.      * 当intern方法被执行,如果字符串常量池已经包含了与当前字符串对象equals的字符串, 
  2113.      * 那么直接从字符串常量池里返回该字符串对象即可,否则会将该字符串对象添加到常量池中 
  2114.      * 并返回. 
  2115.      * 因此对于任意的两个字符串s和t, 
  2116.      * 当且仅当s.equals(t) == true, 
  2117.      * s.intern() == t.intern()才会返回true. 
  2118.      * 所有的字符串字面量以及基于String的常量表达式都会被字符串常量池集中管理和返回. 
  2119.      * 
  2120.      * @return  从字符串常量池返回一个字符串,保持返回的字符串是在常量池中并且是唯一的 
  2121.      */  
  2122.     public native String intern();  
  2123.   
  2124.     /** Hash计算需要的种子 */  
  2125.     private static final int HASHING_SEED;  
  2126.   
  2127.     static {  
  2128.         //当前的纳秒数  
  2129.         long nanos = System.nanoTime();  
  2130.         //当前的毫秒数  
  2131.         long now = System.currentTimeMillis();  
  2132.         //Hash种子利用了String类和System类的加载路径以及当前系统时间的纳秒数、毫秒数  
  2133.         int SEED_MATERIAL[] = {  
  2134.                 System.identityHashCode(String.class),  
  2135.                 System.identityHashCode(System.class),  
  2136.                 (int) (nanos >>> 32),  
  2137.                 (int) nanos,  
  2138.                 (int) (now >>> 32),  
  2139.                 (int) now,  
  2140.                 (int) (System.nanoTime() >>> 2)  
  2141.         };  
  2142.   
  2143.         // 内部实现避免加载类  
  2144.         int h1 = 0;  
  2145.   
  2146.         // Hash种子计算的核心部分  
  2147.         for (int k1 : SEED_MATERIAL) {  
  2148.             k1 *= 0xcc9e2d51;  
  2149.             k1 = (k1 << 15) | (k1 >>> 17);  
  2150.             k1 *= 0x1b873593;  
  2151.   
  2152.             h1 ^= k1;  
  2153.             h1 = (h1 << 13) | (h1 >>> 19);  
  2154.             h1 = h1 * 5 + 0xe6546b64;  
  2155.         }  
  2156.   
  2157.         // tail (always empty, as body is always 32-bit chunks)  
  2158.   
  2159.         // finalization  
  2160.   
  2161.         h1 ^= SEED_MATERIAL.length * 4;  
  2162.   
  2163.         // finalization mix force all bits of a hash block to avalanche  
  2164.         h1 ^= h1 >>> 16;  
  2165.         h1 *= 0x85ebca6b;  
  2166.         h1 ^= h1 >>> 13;  
  2167.         h1 *= 0xc2b2ae35;  
  2168.         h1 ^= h1 >>> 16;  
  2169.   
  2170.         HASHING_SEED = h1;  
  2171.     }  
  2172.   
  2173.     /** 存储另一种Hash散列算法的计算结果,因为int占4个字节共32个bit,因此这里得到的是32位的Hash值 */  
  2174.     private transient int hash32 = 0;  
  2175.   
  2176.     /** 
  2177.      * 针对当前字符串对象计算得到一个32位的Hash值 
  2178.      * 
  2179.      * @return a 返回一个32位的Hash值 
  2180.      */  
  2181.     int hash32() {  
  2182.         int h = hash32;  
  2183.         if (0 == h) {  
  2184.            // Murmur3 hashing函数针对碰撞攻击提供了优秀的保护机制  
  2185.            h = sun.misc.Hashing.murmur3_32(HASHING_SEED, value, 0, value.length);  
  2186.   
  2187.            // 确保最终计算的Hash值不为零,如果计算后得到为零,  
  2188.            // 强制赋值为1,以避免重复进行Hash计算  
  2189.            h = (0 != h) ? h : 1;  
  2190.   
  2191.            hash32 = h;  
  2192.         }  
  2193.         return h;  
  2194.     }  
  2195. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值