国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

String 源碼淺析————終結(jié)篇

Cristalven / 2761人閱讀

摘要:我們?cè)趯?duì)較為熟悉之后,完全可以去嘗試閱讀一些源碼,打開源碼后,如果你英文能力稍微過得去,那么源碼有相當(dāng)詳細(xì)的注釋告訴你的含義,具體用法。

寫在前面

說說這幾天看源碼的感受吧,其實(shí) jdk 中的源碼設(shè)計(jì)是最值得進(jìn)階學(xué)習(xí)的地方。我們?cè)趯?duì) api 較為熟悉之后,完全可以去嘗試閱讀一些 jdk 源碼,打開 jdk 源碼后,如果你英文能力稍微過得去,那么源碼有相當(dāng)詳細(xì)的注釋告訴你 api 的含義,具體用法。假設(shè)平時(shí)在寫代碼的過程中突然忘記了某個(gè) api 的用法,那么有些新手沒讀過源碼的可能順手就打開百度或者谷歌,搜索 api 怎么用?哈哈哈,面向谷歌編程,這樣的狀態(tài)可能會(huì)讓你一年的經(jīng)驗(yàn)重復(fù)n年, 如果是閱讀過源碼,則直接進(jìn)去看看源碼英文注釋,回想一下源碼的實(shí)現(xiàn)即可使用,而且看過源碼后,里面有些代碼細(xì)節(jié)是可以在平時(shí)編碼的過程中直接借鑒的。

廢話有點(diǎn)多啦~~滴滴滴,上車了。。。

上一篇 String 源碼淺析(一) 中已經(jīng)對(duì)String前半部分源碼做了解析,這篇把剩下的方法粗略的總結(jié)下...

String 成員方法

判斷字符串是否相等,該方法繼承自Object類的重寫實(shí)現(xiàn),原則上也是比較字符串中的字符是否相等。

   public boolean equals(Object anObject) {
    //判斷形參跟當(dāng)前字符串對(duì)象地址是否相等,即是否為同一個(gè)對(duì)象,如果相等,則返回true
    if (this == anObject) {
        return true;
    }
    //如果形參為String類型對(duì)象
    if (anObject instanceof String) {
        //強(qiáng)轉(zhuǎn)為String類型對(duì)象
        String anotherString = (String)anObject;
        //當(dāng)前字符串對(duì)象的字符數(shù)組長(zhǎng)度
        int n = value.length;
        //如果當(dāng)前字符串對(duì)象的字符數(shù)組長(zhǎng)度等于形參字符串字符數(shù)組長(zhǎng)度
        if (n == anotherString.value.length) {
            //當(dāng)前字符串字符數(shù)組
            char v1[] = value;
            //形參字符串字符數(shù)組
            char v2[] = anotherString.value;
            //遍歷索引起始位置0
            int i = 0;
            //遍歷當(dāng)前字符串字符數(shù)組,每個(gè)索引位置的字符與形參字符串索引位置字符比較,如果不相等則返回false
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    //以上條件都不滿足,最后返回false
    return false;
}

傳入CharSequence接口形參,實(shí)際是與StringBuffer,StringBuilder比較是否相等,因?yàn)?b>StringBuffer,StringBuilder都實(shí)現(xiàn)了CharSequence接口

public boolean contentEquals(CharSequence cs) {
    //判斷形參是否是AbstractStringBuilder抽象類,實(shí)則因當(dāng)傳入的是其子類:StringBuffer, StringBuilder
    if (cs instanceof AbstractStringBuilder) {
        //如果形參是StringBuffer類型對(duì)象
        if (cs instanceof StringBuffer) {
            //同步鎖,調(diào)用nonSyncContentEquals方法比較兩種是否相等
            synchronized(cs) {
               return nonSyncContentEquals((AbstractStringBuilder)cs);
            }
        } else {
            //如果形參對(duì)象是StringBuilder,則調(diào)用nonSyncContentEquals方法比較兩種是否相等
            return nonSyncContentEquals((AbstractStringBuilder)cs);
        }
    }
    // 如果形參是String對(duì)象,則直接調(diào)用equals方法返回
    if (cs instanceof String) {
        return equals(cs);
    }
    // 如果是其他的CharSequence實(shí)現(xiàn)類,則遍歷,一個(gè)個(gè)字符進(jìn)行比較,找到一個(gè)字符不相等則直接返回false
    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;
        }
    }
    //以上代碼都不成立,走到最后直接返回true
    return true;
}

私有方法,非同步方式(線程不安全)比較與 AbstractStringBuilder 是否相等,實(shí)則是與其子類:StringBuffer, StringBuilder 比較大小,contentEquals(CharSequence cs) 方法中核心比較代碼就是調(diào)用該方法。

  private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
    //當(dāng)前字符串對(duì)象字符數(shù)組
    char v1[] = value;
    //獲取形參字符數(shù)組
    char v2[] = sb.getValue();
    //當(dāng)前字符串對(duì)象字符數(shù)組長(zhǎng)度
    int n = v1.length;
    //如果當(dāng)前字符串對(duì)象字符數(shù)組長(zhǎng)度不等于形參字符數(shù)組長(zhǎng)度,則直接返回false
    if (n != sb.length()) {
        return false;
    }
    //遍歷當(dāng)前字符串對(duì)象字符數(shù)組,與形參字符數(shù)組逐一比較字符,找到一個(gè)字符不相等,則直接返回false
    for (int i = 0; i < n; i++) {
        if (v1[i] != v2[i]) {
            return false;
        }
    }
    //以上條件都不成立,代碼走到最后則直接返回true
    return true;
}

公有方法,比較與StringBuffer對(duì)象是否相等,內(nèi)部實(shí)則直接調(diào)用的contentEquals(CharSequence cs)方法,可以說該方法是StringBuffer的特別版吧。

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

匹配兩個(gè)字符串部分片段是否相等

  public boolean regionMatches(int toffset, String other, int ooffset,
        int len) {
    //當(dāng)前字符串字符數(shù)組
    char ta[] = value;
    //當(dāng)前字符串開始比較的起始位置,即偏移量
    int to = toffset;
    //待比較的字符串字符數(shù)組
    char pa[] = other.value;
    //待比較的字符串起始位置,即偏移量
    int po = ooffset;
    //索引檢查 1.偏移量小于0  2. 偏移量大于總長(zhǎng)度-待比較的長(zhǎng)度
    //以上兩種情況直接返回false
    if ((ooffset < 0) || (toffset < 0)
            || (toffset > (long)value.length - len)
            || (ooffset > (long)other.value.length - len)) {
        return false;
    }
    //遍歷,找出不相等的字符,則返回false
    while (len-- > 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    //不出意外,最終則返回true
    return true;
}

匹配兩個(gè)字符串部分片段是否相等,同時(shí)判斷是否忽略大小寫

public boolean regionMatches(boolean ignoreCase, int toffset,
        String other, int ooffset, int len) {
    //當(dāng)前字符串字符數(shù)組
    char ta[] = value;
    //當(dāng)前字符串開始比較的起始位置,即偏移量
    int to = toffset;
    //待比較的字符串字符數(shù)組
    char pa[] = other.value;
    //待比較的字符串起始位置,即偏移量
    int po = ooffset;
    //索引檢查 1.偏移量小于0  2. 偏移量大于總長(zhǎng)度-待比較的長(zhǎng)度
    //以上兩種情況直接返回false
    if ((ooffset < 0) || (toffset < 0)
            || (toffset > (long)value.length - len)
            || (ooffset > (long)other.value.length - len)) {
        return false;
    }
    //遍歷檢查字符是否相等,相等則跳過
    while (len-- > 0) {
        char c1 = ta[to++];
        char c2 = pa[po++];
        if (c1 == c2) {
            continue;
        }
        //如果字符不相等,且需要忽略大小寫比較
        if (ignoreCase) {
            //字符轉(zhuǎn)換為大寫
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);
            //如果相等,則繼續(xù)跳過
            if (u1 == u2) {
                continue;
            }
            //轉(zhuǎn)換為小寫進(jìn)行比較,如果相等則繼續(xù)跳過
            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                continue;
            }
        }
        //否則發(fā)現(xiàn)不相等,則直接返回false
        return false;
    }
    //不出意外,最終返回true
    return true;
}

忽略大小寫比較字符串大小

 public boolean equalsIgnoreCase(String anotherString) {
    //一句三目運(yùn)算直接搞定
    //如果當(dāng)前字符串對(duì)象地址與形參字符串相等,則返回true
    //否則判斷形參字符串是否為空,形參字符串長(zhǎng)度是否與當(dāng)前字符串長(zhǎng)度相等,直接調(diào)用regionMatches比較兩個(gè)字符串所有字符是否相等,同時(shí)忽略大小寫比較
    //以上全部為true則相等
    return (this == anotherString) ? true
            : (anotherString != null)
            && (anotherString.value.length == value.length)
            && regionMatches(true, 0, anotherString, 0, value.length);
}

比較兩個(gè)字符串是否相等,該方法實(shí)現(xiàn)自Comparable接口,返回 int 結(jié)果,等于0,則字符串相等,小于0,則前者小于后者,大于0,則前者大于后者

  public int compareTo(String anotherString) {
    //當(dāng)前字符串字符數(shù)組長(zhǎng)度
    int len1 = value.length;
    //待比較字符串字符數(shù)組長(zhǎng)度
    int len2 = anotherString.value.length;
    //獲取較小的長(zhǎng)度
    int lim = Math.min(len1, len2);
    //當(dāng)前字符串字符數(shù)組
    char v1[] = value;
    //待比較的字符串字符數(shù)組
    char v2[] = anotherString.value;
    //索引位置0開始
    int k = 0;
    //遍歷較小的字符數(shù)組
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        //如果字符不相等
        if (c1 != c2) {
            //返回字符之差
            return c1 - c2;
        }
        k++;
    }
    //如果字符都相等,則返回長(zhǎng)度之差
    return len1 - len2;
}

使用默認(rèn)比較器不區(qū)分大小寫比較兩個(gè)字符串大小

//初始化默認(rèn)的比較器
public static final Comparator CASE_INSENSITIVE_ORDER
                                     = new CaseInsensitiveComparator();
//默認(rèn)的比較器,不區(qū)分大小寫                          
private static class CaseInsensitiveComparator
        implements Comparator, java.io.Serializable {
    // use serialVersionUID from JDK 1.2.2 for interoperability
    private static final long serialVersionUID = 8575799808933029326L;
    public int compare(String s1, String s2) {
        //第一個(gè)字符串長(zhǎng)度
        int n1 = s1.length();
        //第二個(gè)字符串長(zhǎng)度
        int n2 = s2.length();
        //取小
        int min = Math.min(n1, n2);
        //遍歷較小的字符串
        for (int i = 0; i < min; i++) {
            //獲取指定索引字符
            char c1 = s1.charAt(i);
            char c2 = s2.charAt(i);
            //如果字符不相等
            if (c1 != c2) {
                //轉(zhuǎn)化為大寫
                c1 = Character.toUpperCase(c1);
                c2 = Character.toUpperCase(c2);
                //轉(zhuǎn)化為大寫后比較,不相等
                if (c1 != c2) {
                    //轉(zhuǎn)化為小寫繼續(xù)比較
                    c1 = Character.toLowerCase(c1);
                    c2 = Character.toLowerCase(c2);
                    //轉(zhuǎn)化為小寫字符,不相等
                    if (c1 != c2) {
                        //直接返回字符之差
                        return c1 - c2;
                    }
                }
            }
        }
        //不出意外,最終返回長(zhǎng)度之差
        return n1 - n2;
    }
    /** Replaces the de-serialized object. */
    private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
}

//內(nèi)部直接調(diào)用默認(rèn)比較器的compare方法
public int compareToIgnoreCase(String str) {
    return CASE_INSENSITIVE_ORDER.compare(this, str);
}

從指定偏移量開始,判斷是否以指定字符串開頭

 public boolean startsWith(String prefix, int toffset) {
    //當(dāng)前字符串字符數(shù)組
    char ta[] = value;
    //偏移量
    int to = toffset;
    //指定字符串前綴字符數(shù)組
    char pa[] = prefix.value;
    //索引位置0開始
    int po = 0;
    //指定字符串前綴數(shù)組長(zhǎng)度
    int pc = prefix.value.length;
    //偏移量小于0 或者 //偏移量大于總長(zhǎng)度-字符串前綴長(zhǎng)度,則直接返回false
    if ((toffset < 0) || (toffset > value.length - pc)) {
        return false;
    }
    //遍歷前綴字符串
    while (--pc >= 0) {
        //從偏移量開始檢索,找到字符不相等,則返回false
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    //不出意外,最后則返回true
    return true;
}

從字符串開頭,判斷是否以指定字符串開頭

 public boolean startsWith(String prefix) {
    //直接調(diào)用startsWith重載方法,偏移量為0
    return startsWith(prefix, 0);
}

判斷是否以指定字符串結(jié)尾,內(nèi)部直接調(diào)用的 startsWith 方法,偏移量為總字符串長(zhǎng)度-后綴字符串長(zhǎng)度即可。

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

從指定偏移量開始,搜索指定字符在字符串中第一次出現(xiàn)的索引位置

 public int indexOf(int ch, int fromIndex) {
    //當(dāng)前字符串字符數(shù)組長(zhǎng)度
    final int max = value.length;
    //如果偏移量小于0,則重置為0
    if (fromIndex < 0) {
        fromIndex = 0;
    } else if (fromIndex >= max) {
        //偏移量大于總長(zhǎng)度,則返回-1,意味著找不到指定字符
        return -1;
    }
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
        //當(dāng)前字符串字符數(shù)組
        final char[] value = this.value;
        //從偏移量位置開始遍歷
        for (int i = fromIndex; i < max; i++) {
            //找到相等的字符,則返回索引
            if (value[i] == ch) {
                return i;
            }
        }
        //找不到則返回-1
        return -1;
    } else {
        return indexOfSupplementary(ch, fromIndex);
    }
}

查找指定字符在字符串中第一次出現(xiàn)的索引位置,從偏移量0開始遍歷查找

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

查找指定字符在字符串中最后一次出現(xiàn)的索引位置,從指定偏移量開始遍歷

  public int lastIndexOf(int ch, int fromIndex) {
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
        //當(dāng)前字符串字符數(shù)組
        final char[] value = this.value;
        //偏移量與字符串最后的位置取小
        int i = Math.min(fromIndex, value.length - 1);
        //從后遍歷字符數(shù)組
        for (; i >= 0; i--) {
            //找到相等的字符,返回索引
            if (value[i] == ch) {
                return i;
            }
        }
        //找不到則返回-1
        return -1;
    } else {
        return lastIndexOfSupplementary(ch, fromIndex);
    }
}

查找指定字符在字符串中最后一次出現(xiàn)的索引位置,從字符串最后一個(gè)索引位置開始遍歷查找

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

從指定位置開始,查找字符串在源字符串中第一次出現(xiàn)的的索引位置,內(nèi)部實(shí)則直接調(diào)用的indexOf內(nèi)部靜態(tài)方法

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

查找字符串在源字符串中第一次出現(xiàn)的的索引位置,內(nèi)部實(shí)則直接調(diào)用的上述indexOf方法,fromIndex默認(rèn)從0開始

 public int indexOf(String str) {
    return indexOf(str, 0);
}

從指定位置開始,查找字符串在源字符串中最后一次出現(xiàn)的的索引位置,內(nèi)部實(shí)則直接調(diào)用的lastIndexOf內(nèi)部靜態(tài)方法

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

查找字符串在源字符串中最后一次出現(xiàn)的的索引位置,內(nèi)部實(shí)則直接調(diào)用的上述lastIndexOf方法,fromIndex默認(rèn)從value.length開始

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

按照指定區(qū)間裁剪字符串,返回子字符串,beginIndex起始位置(包含),endIndex結(jié)束位置(不包含)

    public String substring(int beginIndex, int endIndex) {
    //起始位置小于0,拋出索引越界異常
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    //結(jié)束位置大于字符串總長(zhǎng)度,則拋出索引越界異常
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    //待截取的字符串長(zhǎng)度
    int subLen = endIndex - beginIndex;
    //待截取的字符串長(zhǎng)度小于0,則拋出索引越界異常
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    //三目判斷 起始位置等于0,并且結(jié)束位置等于字符串長(zhǎng)度,則表示為截取總長(zhǎng)度,返回當(dāng)前字符串對(duì)象
    //否則重新new一個(gè)字符串實(shí)例,從beginIndex開始,截取subLen長(zhǎng)度
    return ((beginIndex == 0) && (endIndex == value.length)) ? this
            : new String(value, beginIndex, subLen);
}

從起始位置beginIndex開始截取源字符串到結(jié)尾,返回子字符串

 public String substring(int beginIndex) {
    //起始位置小于0,拋出索引越界異常
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    //待截取的字符串長(zhǎng)度
    int subLen = value.length - beginIndex;
    //待截取的字符串長(zhǎng)度小于0,則拋出索引越界異常
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    //三目判斷 起始位置等于0,則表示為截取總長(zhǎng)度,返回當(dāng)前字符串對(duì)象,否則重新new一個(gè)新的字符串實(shí)例,從beginIndex開始,截取subLen長(zhǎng)度
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

按照指定區(qū)間裁剪字符串,返回CharSequence接口,beginIndex起始位置(包含),endIndex結(jié)束位置(不包含),內(nèi)部實(shí)則直接調(diào)用的substring方法,只是返回的是最上層接口罷了

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

字符串拼接,將目標(biāo)字符串拼接在尾部,返回新的字符串

  public String concat(String str) {
    //待拼接的字符串長(zhǎng)度
    int otherLen = str.length();
    //如果待拼接的字符串長(zhǎng)度等于0,則直接返回當(dāng)前字符串對(duì)象
    if (otherLen == 0) {
        return this;
    }
    //當(dāng)前字符串長(zhǎng)度
    int len = value.length;
    //將當(dāng)前字符串字符數(shù)組拷貝到新的字符數(shù)組buf[]中,長(zhǎng)度擴(kuò)容至len + otherLen
    char buf[] = Arrays.copyOf(value, len + otherLen);
    //將待拼接的字符數(shù)組拷貝至buf[]中,從len開始,理論上這部操作完之后,字符數(shù)組已經(jīng)拼接成功了
    str.getChars(buf, len);
    //利用最新的字符數(shù)組,重新new一個(gè)新的字符串實(shí)例返回
    return new String(buf, true);
}

將字符串中指定字符oldChar替換為新的字符newChar

  public String replace(char oldChar, char newChar) {
    //如果舊的字符跟新的字符不相等,才執(zhí)行替換邏輯,否則直接返回當(dāng)前字符串對(duì)象
    if (oldChar != newChar) {
        //當(dāng)前字符串長(zhǎng)度
        int len = value.length;
        //索引從-1開始
        int i = -1;
        //當(dāng)前字符串字符數(shù)組
        char[] val = value;
        //遍歷當(dāng)前字符數(shù)組,從0開始,因?yàn)?+i之后等于0
        while (++i < len) {
            //找到與oldChar相等的字符,則中斷循環(huán)
            if (val[i] == oldChar) {
                break;
            }
        }
        //如果oldChar索引位置i小于當(dāng)前字符數(shù)組長(zhǎng)度,意味著在當(dāng)前字符串中找到了oldChar
        if (i < len) {
            //初始化字符串長(zhǎng)度的字符數(shù)組
            char buf[] = new char[len];
            //從0開始遍歷到oldChar所在位置,將字符放入buf
            for (int j = 0; j < i; j++) {
                buf[j] = val[j];
            }
            //從oldChar索引位置i開始遍歷到字符串結(jié)尾
            while (i < len) {
                //當(dāng)前字符
                char c = val[i];
                //如果當(dāng)前字符等于oldChar,則newChar賦值給buf[i],否則不變
                buf[i] = (c == oldChar) ? newChar : c;
                i++;
            }
            //最后根據(jù)buf數(shù)組重新new一個(gè)新的字符串實(shí)例返回
            return new String(buf, true);
        }
    }
    return this;
}

根據(jù)字符串正則regex匹配字符串,返回boolean,內(nèi)部實(shí)則是調(diào)用正則匹配的api方法

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

判斷字符串是否包含指定字符序列CharSequence,內(nèi)部實(shí)則是調(diào)用indexOf方法,判斷返回結(jié)果是否大于-1

 public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

根據(jù)給定的新的子字符串replacement,替換第一個(gè)匹配給定的正則表達(dá)式regex的子字符串,內(nèi)部實(shí)則調(diào)用的是Matcher類的replaceFirst方法

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

根據(jù)給定的新的子字符串replacement,替換所有匹配給定的正則表達(dá)式regex的子字符串,內(nèi)部實(shí)則調(diào)用的是Matcher類的replaceAll方法

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

更加通用的字符串替換方法,將匹配到的target字符序列全部替換為replacement字符序列,內(nèi)部調(diào)用的也是Matcher類的replaceAll方法

 public String replace(CharSequence target, CharSequence replacement) {
    return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
            this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}

去除字符串前后空格

    public String trim() {
    //當(dāng)前字符串長(zhǎng)度
    int len = value.length;
    //索引標(biāo)志位
    int st = 0;
    //當(dāng)前字符串字符數(shù)組
    char[] val = value;    
    //從0開始遍歷循環(huán),查找到空格的字符,則索引往前+1
    while ((st < len) && (val[st] <= " ")) {
        st++;
    }
    //從字符串尾部開始遍歷循環(huán),查找到空格字符,則長(zhǎng)度往后-1
    while ((st < len) && (val[len - 1] <= " ")) {
        len--;
    }
    //如果st索引大于0或者長(zhǎng)度len小于總長(zhǎng)度,則返回裁剪字符串st偏移量開始,裁剪len長(zhǎng)度,否則直接返回當(dāng)前字符串對(duì)象
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

字符串轉(zhuǎn)化toString,繼承自Object重寫的方法,直接返回當(dāng)前字符串對(duì)象

 public String toString() {
    return this;
}

字符串轉(zhuǎn)化為字符數(shù)組

  public char[] toCharArray() {
    //初始化字符串長(zhǎng)度的字符數(shù)組
    char result[] = new char[value.length];
    //將字符串本身的字符數(shù)組拷貝至result[]并返回結(jié)果
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
}

String 靜態(tài)方法

不對(duì)外公開的內(nèi)部靜態(tài)方法,從字符串source指定索引fromIndex開始遍歷,從偏移量sourceOffset,在原始字符串長(zhǎng)度sourceCount范圍內(nèi)查找目標(biāo)字符串target中偏移量targetOffset開始,長(zhǎng)度為targetCount的字符串索引第一次出現(xiàn)的位置。

static int indexOf(char[] source, int sourceOffset, int sourceCount,
        char[] target, int targetOffset, int targetCount,
        int fromIndex) {
    //如果起始位置大于等于源字符串指定長(zhǎng)度
    if (fromIndex >= sourceCount) {
        //如果目標(biāo)字符串查找的長(zhǎng)度為0,則直接返回源字符串長(zhǎng)度,否則返回-1表示未找到
        return (targetCount == 0 ? sourceCount : -1);
    }
    //起始位置小于0
    if (fromIndex < 0) {
        //重置為0
        fromIndex = 0;
    }
    //目標(biāo)字符串長(zhǎng)度為0,代表為空字符串”“
    if (targetCount == 0) {
        //直接返回起始位置
        return fromIndex;
    }
    //目標(biāo)字符串第一個(gè)字符
    char first = target[targetOffset];
    //從源字符偏移量開始,計(jì)算最大的遍歷次數(shù)
    int max = sourceOffset + (sourceCount - targetCount);
    //遍歷
    for (int i = sourceOffset + fromIndex; i <= max; i++) {
        //循環(huán)找出第一個(gè)字符
        if (source[i] != first) {
            while (++i <= max && source[i] != first);
        }
        //todo 這段暫時(shí)沒看明白 by zhangshaolin
        if (i <= max) {
            int j = i + 1;
            int end = j + targetCount - 1;
            for (int k = targetOffset + 1; j < end && source[j]
                    == target[k]; j++, k++);
            if (j == end) {
                /* Found whole string. */
                return i - sourceOffset;
            }
        }
    }
    //最終沒找到 則返回-1
    return -1;
}

不對(duì)外公開的靜態(tài)方法,上述方法的另一個(gè)重載形式,內(nèi)部實(shí)則直接調(diào)用的上述方法,targetCount默認(rèn)傳入target.value.length

   static int indexOf(char[] source, int sourceOffset, int sourceCount,
        String target, int fromIndex) {
    return indexOf(source, sourceOffset, sourceCount,
                   target.value, 0, target.value.length,
                   fromIndex);
}

不對(duì)外公開的內(nèi)部靜態(tài)方法,從字符串source指定索引fromIndex開始遍歷,從偏移量sourceOffset,在原始字符串長(zhǎng)度sourceCount范圍內(nèi)查找目標(biāo)字符串target中偏移量targetOffset開始,長(zhǎng)度為targetCount的字符串索引第一次出現(xiàn)的位置。

 static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
        char[] target, int targetOffset, int targetCount,
        int fromIndex) {
    //源字符長(zhǎng)度-目標(biāo)字符長(zhǎng)度,獲取起始位置
    int rightIndex = sourceCount - targetCount;
    //起始位置小于0,直接返回-1表示未找到目標(biāo)
    if (fromIndex < 0) {
        return -1;
    }
    //如果形參起始位置大于計(jì)算的實(shí)際起始位置,則直接賦值給fromIndex
    if (fromIndex > rightIndex) {
        fromIndex = rightIndex;
    }
    //如果目標(biāo)字符串長(zhǎng)度為0,表示為空字符串,則直接返回起始位置
    if (targetCount == 0) {
        return fromIndex;
    }
    //獲取目標(biāo)字符串最后一個(gè)索引位置
    int strLastIndex = targetOffset + targetCount - 1;
    //獲取目標(biāo)字符串最后一個(gè)字符
    char strLastChar = target[strLastIndex];
    //獲取最小遍歷次數(shù)
    int min = sourceOffset + targetCount - 1;
    //最小遍歷次數(shù)+起始位置
    int i = min + fromIndex;
//循環(huán)查找最后一個(gè)字符
startSearchForLastChar:
    while (true) {
        while (i >= min && source[i] != strLastChar) {
            i--;
        }
        //如果i start) {
            if (source[j--] != target[k--]) {
                i--;
                //找不到,繼續(xù)跳過外層循環(huán)
                continue startSearchForLastChar;
            }
        }
        return start - sourceOffset + 1;
    }
}

不對(duì)外公開的靜態(tài)方法,上述方法的另一個(gè)重載形式,內(nèi)部實(shí)則直接調(diào)用的上述方法,targetCount默認(rèn)傳入target.value.length

 static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
        String target, int fromIndex) {
    return lastIndexOf(source, sourceOffset, sourceCount,
                   target.value, 0, target.value.length,
                   fromIndex);
}

將任意Object對(duì)象轉(zhuǎn)化為字符串對(duì)象返回,內(nèi)部實(shí)則也是調(diào)用的ObjecttoString方法,返回結(jié)果取決于該方法的具體實(shí)現(xiàn)

  public static String valueOf(Object obj) {
    //如果obj為空,則返回"null",否則返回對(duì)象的toString返回的字符串結(jié)果
    return (obj == null) ? "null" : obj.toString();
}

將字符數(shù)組轉(zhuǎn)化為字符串對(duì)象返回,內(nèi)部實(shí)際是用字符數(shù)組為參數(shù) 重新 new 了一個(gè)新的字符串對(duì)象,并返回

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

將字符數(shù)組轉(zhuǎn)化為字符串對(duì)象返回,同時(shí)指定索引偏移量offset,截取的長(zhǎng)度count,內(nèi)部實(shí)際是重新 new 了一個(gè)新的字符串對(duì)象,并返回

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

與上一個(gè)方法效果一致,只是方法名稱不同罷了

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

valueOf(char data[])效果一致,只是方法名稱不同罷了

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

boolean類型數(shù)據(jù)轉(zhuǎn)化為字符串對(duì)象返回

 public static String valueOf(boolean b) {
    //為真 則返回"true" 否則返回"false"
    return b ? "true" : "false";
}

將字符轉(zhuǎn)化為字符串對(duì)象返回

 public static String valueOf(char c) {
    //初始化字符數(shù)組
    char data[] = {c};
    //重新new一個(gè)新的字符串對(duì)象返回
    return new String(data, true);
}

將int數(shù)據(jù)轉(zhuǎn)換為字符串對(duì)象返回,內(nèi)部實(shí)際是調(diào)用的Integer.toString()方法

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

將long數(shù)據(jù)轉(zhuǎn)換為字符串對(duì)象返回,內(nèi)部實(shí)際是調(diào)用的Long.toString()方法

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

將float數(shù)據(jù)轉(zhuǎn)換為字符串對(duì)象返回,內(nèi)部實(shí)際是調(diào)用的Float.toString()方法

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

將double數(shù)據(jù)轉(zhuǎn)換為字符串對(duì)象返回,內(nèi)部實(shí)際是調(diào)用的Double.toString()方法

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

簡(jiǎn)單總結(jié)

String源碼全部大致過了一遍之后,感慨 jdk 代碼設(shè)計(jì)的強(qiáng)大,幾天時(shí)間要完全看懂是不容易的,目前也還有很多地方?jīng)]有完全明白

源碼并不可怕,可怕的是自己的畏懼心理,認(rèn)為源碼很難啃不動(dòng),其實(shí)不然,下定決心看下去,遇到不懂的可以先pass,后面再回頭看可能就豁然開朗了。

String 內(nèi)部本質(zhì)就是操作字符數(shù)組 value[]

因?yàn)楸举|(zhì)就是操作字符數(shù)組,內(nèi)部用到了大量的Arrays.copyOf,以及System.arraycopy方法

最后

看源碼不易,如果文中有錯(cuò)誤之處,還請(qǐng)留言指出,一起學(xué)習(xí),一起進(jìn)步,謝謝!

更多原創(chuàng)文章會(huì)第一時(shí)間推送公眾號(hào)【張少林同學(xué)】,歡迎關(guān)注!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/72857.html

相關(guān)文章

  • Underscore 整體架構(gòu)淺析

    摘要:支持形式的調(diào)用這其實(shí)是非常經(jīng)典的無構(gòu)造,其實(shí)就是一個(gè)構(gòu)造函數(shù),的結(jié)果就是一個(gè)對(duì)象實(shí)例,該實(shí)例有個(gè)屬性,屬性值是。 前言 終于,樓主的「Underscore 源碼解讀系列」underscore-analysis 即將進(jìn)入尾聲,關(guān)注下 timeline 會(huì)發(fā)現(xiàn)樓主最近加快了解讀速度。十一月,多事之秋,最近好多事情搞的樓主心力憔悴,身心俱疲,也想盡快把這個(gè)系列完結(jié)掉,也好了卻一件心事。 本文...

    ningwang 評(píng)論0 收藏0
  • 一個(gè)App完成入門-終結(jié)(八)- 應(yīng)用收官

    摘要:經(jīng)過以上幾步的學(xué)習(xí),我們終于來到最后一個(gè)步驟了,應(yīng)用也接近尾聲。一個(gè)應(yīng)用的一個(gè)平臺(tái)對(duì)應(yīng)了一個(gè)證書證書的是應(yīng)用的標(biāo)示,更準(zhǔn)確的說,平臺(tái)證書中的包名平臺(tái)證書中的是標(biāo)示應(yīng)用唯一性的憑證。 經(jīng)過以上幾步的學(xué)習(xí),我們終于來到最后一個(gè)步驟了,應(yīng)用APP也接近尾聲。 通過之前的幾節(jié)教程,不知道您對(duì)使用DeviceOne開發(fā)一個(gè)應(yīng)用是不是已經(jīng)得心應(yīng)手了,本節(jié)教程將教會(huì)大家如何在開發(fā)完成之后通過Devi...

    DandJ 評(píng)論0 收藏0
  • 一個(gè)App完成入門-終結(jié)(八)- 應(yīng)用收官

    摘要:經(jīng)過以上幾步的學(xué)習(xí),我們終于來到最后一個(gè)步驟了,應(yīng)用也接近尾聲。一個(gè)應(yīng)用的一個(gè)平臺(tái)對(duì)應(yīng)了一個(gè)證書證書的是應(yīng)用的標(biāo)示,更準(zhǔn)確的說,平臺(tái)證書中的包名平臺(tái)證書中的是標(biāo)示應(yīng)用唯一性的憑證。 經(jīng)過以上幾步的學(xué)習(xí),我們終于來到最后一個(gè)步驟了,應(yīng)用APP也接近尾聲。 通過之前的幾節(jié)教程,不知道您對(duì)使用DeviceOne開發(fā)一個(gè)應(yīng)用是不是已經(jīng)得心應(yīng)手了,本節(jié)教程將教會(huì)大家如何在開發(fā)完成之后通過Devi...

    leap_frog 評(píng)論0 收藏0
  • san.parseExpr 源碼學(xué)習(xí)

    摘要:方法的產(chǎn)生式如下由得這個(gè)函數(shù),包含了除布爾值的表達(dá)式之外的,各個(gè)表示數(shù)據(jù)得表達(dá)式的解析部分。這里我的鏈接直接指向了上關(guān)于線性漸變的形式語法部分,可以看到這部分對(duì)線性漸變語法的描述,和我上面解析的時(shí)候所用的產(chǎn)生式如出一轍。 博客源地址:https://github.com/LeuisKen/l...相關(guān)評(píng)論還請(qǐng)到 issue 下。 方法說明 san.parseExpr是San中主模塊下的...

    Donald 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<