1. 程式人生 > >java源碼解析之String類(二)

java源碼解析之String類(二)

nta sequence objects 常量 解析 字節 整體 require sync

上一節主要介紹了String類的一些構造方法,主要分為四類

  • 無參構造器:String(),創建一個空字符串"",區別於null字符串,""已經初始化,null並未初始化
  • 副本構造器:String(String s),簡單的賦值,得到的是一個副本,倆個引用指向的是常量池中的同一個String,但是String是不可變的,所有用意不大
  • byte類構造器:String(byte[] b),將byte數組轉換為String,註意並不是簡單的賦值,而是整體copy一份
  • char類構造器:String(char[] c),將char數組轉換成String,註意並不是簡單的賦值,而是整體copy一份
  • codepoints構構器:String(int[] i),將超過char表示範圍的字符轉換為為String
  • String緩存流的轉換:String(StringBuffer),將字符換緩沖流轉換為String
    /*
     * 獲得字符串的長度,也就是屬性value數組的長度
     */
    public int length() {
        return value.length;
    }

    /*
     * 判斷字符串是否為空,也就是判斷屬性value數組的長度是否等於0
     */
    public boolean isEmpty() {
        return value.length == 0;
    }

    /*
     * charAt方法可以直接獲取當前下標對應的字符,這對於判斷某個位置的字符值很方便
     * 區別於
     
*/ public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; } /* * 返回指定索引處的字符(Unicode代碼點)。 codePoint在上一章已經介紹過了,具體就是那些超出byte和char表示方位的字符 */ public
int codePointAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return Character.codePointAtImpl(value, index, value.length); } /* * 返回指定索引之前的字符(Unicode代碼點)。 */ public int codePointBefore(int index) { int i = index - 1; if ((i < 0) || (i >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return Character.codePointBeforeImpl(value, index, 0); } /* * 返回此 String指定文本範圍內的Unicode代碼點數。 */ public int codePointCount(int beginIndex, int endIndex) { if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex); } /* * 返回此String中的索引,該索引通過codePointOffset代碼點從給定的index偏移。 * index和codePointOffset給出的文本範圍內的未配對代理計為每個代碼點。 * */ public int offsetByCodePoints(int index, int codePointOffset) { if (index < 0 || index > value.length) { throw new IndexOutOfBoundsException(); } return Character.offsetByCodePointsImpl(value, 0, value.length, index, codePointOffset); } /* * 將此字符串復制給dst字節數組,默認為整體復制,其中dstBegin為目標數組dst中的開始位置 * 此方法為包訪問權限,所以我們並沒有調用的權限 */ void getChars(char dst[], int dstBegin) { System.arraycopy(value, 0, dst, dstBegin, value.length); } /* * 將此字符串的額指定位置開始到指定位置結束復制給dst字節數組,其中dstBegin為目標數組dst的開始位置, * srcBegin和srcEnd分別為本字符串的開始位置和結束位置 */ public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } if (srcEnd > value.length) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } /* * 方法已過時 * 使用平臺的默認字符集將此 String編碼為字節序列,將結果存儲到新的字節數組中,可以指定字符串的開始位置和結束位置, * 但結果往往是不正確的,在源碼中我們可以看到,僅僅是將字符串的每一位字符強轉成字節類型,實際用處很少。 * */ @Deprecated public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) { if (srcBegin < 0) { throw new StringIndexOutOfBoundsException(srcBegin); } if (srcEnd > value.length) { throw new StringIndexOutOfBoundsException(srcEnd); } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException(srcEnd - srcBegin); } Objects.requireNonNull(dst); int j = dstBegin; int n = srcEnd; int i = srcBegin; char[] val = value; /* avoid getfield opcode */ while (i < n) { dst[j++] = (byte) val[i++]; } } /* * 指定編碼字符集將此 String編碼為字節序列,將結果存儲到新的字節數組中 */ public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException(); return StringCoding.encode(charsetName, value, 0, value.length); } /* * 指定編碼字符集將此 String編碼為字節序列,將結果存儲到新的字節數組中 */ public byte[] getBytes(Charset charset) { if (charset == null) throw new NullPointerException(); return StringCoding.encode(charset, value, 0, value.length); } /* * 使用平臺的默認字符集將此 String編碼為字節序列,將結果存儲到新的字節數組中 */ public byte[] getBytes() { return StringCoding.encode(value, 0, value.length); } /* * String重寫Object類的equals方法,詳細閱讀源碼,我們發現形參是Object類型,那麽在實際傳參的過程當中 * 除了String類型,別的引用類型都會返回false,重點註意的是StringBuffer和StringBuild,在實際比較的時候一定要先進行轉換 * equals實際比較的就是字符串的每一位依次進行比較,直到全部比較完畢都沒有不一樣的才返回true */ public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } /* * 將此字符串與指定的StringBuffer進行 比較內容是否相等 */ public boolean contentEquals(StringBuffer sb) { return contentEquals((CharSequence) sb); } private boolean nonSyncContentEquals(AbstractStringBuilder sb) { char v1[] = value; char v2[] = sb.getValue(); int n = v1.length; if (n != sb.length()) { return false; } for (int i = 0; i < n; i++) { if (v1[i] != v2[i]) { return false; } } return true; } /* * 將此字符串與指定的CharSequence進行內容比較是否相等 */ public boolean contentEquals(CharSequence cs) { // Argument is a StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { if (cs instanceof StringBuffer) { synchronized (cs) { return nonSyncContentEquals((AbstractStringBuilder) cs); } } else { return nonSyncContentEquals((AbstractStringBuilder) cs); } } // Argument is a String if (cs instanceof String) { return equals(cs); } // Argument is a generic CharSequence char v1[] = value; int n = v1.length; if (n != cs.length()) { return false; } for (int i = 0; i < n; i++) { if (v1[i] != cs.charAt(i)) { return false; } } return true; } /* * 能用一行代價解決的事就不用倆行,三元運算符?:直接解決。其中regionMatches(true, 0, anotherString, 0, value.length)是測試是否相等的函數 * 第一個參數true代表忽略大小寫 */ public boolean equalsIgnoreCase(String anotherString) { return (this == anotherString) ? true : (anotherString != null) && (anotherString.value.length == value.length) && regionMatches(true, 0, anotherString, 0, value.length); }

java源碼解析之String類(二)