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