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

資訊專欄INFORMATION COLUMN

JDK源碼解析系列之String 之一

gnehc / 526人閱讀

摘要:接口解釋這個序列化接口沒有任何方法和域,僅用于標(biāo)識序列化的語意。用于對兩個實(shí)例化對象比較大小這個接口是一個只讀的字符序列。的序列化機(jī)制是通過在運(yùn)行時(shí)判斷類的來驗(yàn)證版本一致性的。然后從開始再對每一個字符進(jìn)行判斷是不是所要替換的字符。

1 接口解釋
(1)Serializable 這個序列化接口沒有任何方法和域,僅用于標(biāo)識序列化的語意。

(2)Comparable 用于對兩個實(shí)例化對象比較大小

(3)CharSequence 這個接口是一個只讀的字符序列。包括length(),
charAt(int index), subSequence(int start, int end)這幾個API接口

2 主要變量

(1)private final char value[];
可以看到,value[]是存儲String的內(nèi)容的,即當(dāng)使用String str = "abcd";
的時(shí)候,本質(zhì)上,"abcd"是存儲在一個char類型的數(shù)組中的。

(2) private int hash;

而hash是String實(shí)例化的hashcode的一個緩存。因?yàn)镾tring經(jīng)常被用于比較,比如在HashMap中。
如果每次進(jìn)行比較都重新計(jì)算hashcode的值的話,那無疑是比較麻煩的,而保存一個hashcode的緩存無疑能優(yōu)化這樣的操作。

(3)private static final long serialVersionUID = -6849794470754667710L;

Java的序列化機(jī)制是通過在運(yùn)行時(shí)判斷類的serialVersionUID來驗(yàn)證版本一致性的。在進(jìn)行反序列化時(shí),JVM會把傳來
的字節(jié)流中的serialVersionUID與本地相應(yīng)實(shí)體(類)的serialVersionUID進(jìn)行比較,如果相同就認(rèn)為是一致的,可以進(jìn)行反序
列化,否則就會出現(xiàn)序列化版本不一致的異常,如果我們不希望通過編譯來強(qiáng)制劃分軟件版本,即實(shí)現(xiàn)序列化接口的實(shí)體能夠兼容先前版本,
未作更改的類,就需要顯式地定義一個名為serialVersionUID,類型為long的變量,不修改這個變量值的序列化實(shí)體都可以相互進(jìn)行
串行化和反串行化

(4) private static final ObjectStreamField[] serialPersistentFields =

    new ObjectStreamField[0];

3 構(gòu)造方法
(1) public String()
(2) public String(String original)
(3) public String(char value[])
(4) public String(char value[], int offset, int count)
(5) public String(int[] codePoints, int offset, int count)
(6) public String(byte ascii[], int hibyte, int offset, int count)
(7) public String(byte ascii[], int hibyte)
(8) public String(byte bytes[], int offset, int length, String charsetName)
(9) public String(byte bytes[], int offset, int length, Charset charset)
(10)public String(byte bytes[], String charsetName)
(11)public String(byte bytes[], Charset charset)
(12)public String(byte bytes[], int offset, int length)
(13)public String(byte bytes[])
(14)public String(StringBuffer buffer)
(15)public String(StringBuilder builder)
String支持多種初始化方法,包括接收String,char[],byte[],StringBuffer等多種參數(shù)類型的初始化方法。
但本質(zhì)上,其實(shí)就是將接收到的參數(shù)傳遞給全局變量value[]。

4 內(nèi)部方法

(1)public int length() {

    return value.length;
}

(2)public boolean isEmpty() {

    return value.length == 0;
}

(3)public char charAt(int index) {

    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
  }

知道了String其實(shí)內(nèi)部是通過char[]實(shí)現(xiàn)的,那么就不難發(fā)現(xiàn)length(),isEmpty(),charAt()這些方法其實(shí)就是在內(nèi)部調(diào)用數(shù)組的方法。
(4)//返回指定索引的代碼點(diǎn)
  public int codePointAt(int index) {

   if ((index < 0) || (index >= value.length)) {
       throw new StringIndexOutOfBoundsException(index);
   }
   return Character.codePointAtImpl(value, index, value.length);

}

//返回指定索引前一個代碼點(diǎn)
(5) 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);
}

  //返回指定起始到結(jié)束段內(nèi)字符個數(shù)
(6)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);
 }

  //返回指定索引加上codepointOffset后得到的索引值
(7)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);
}

//將字符串復(fù)制到dst數(shù)組中,復(fù)制到dst數(shù)組中的起始位置可以指定。值得注意的是,該方法并沒有檢測復(fù)制到dst數(shù)組后是否越界。

(8) void getChars(char dst[], int dstBegin) {

    System.arraycopy(value, 0, dst, dstBegin, value.length);
}

(9) 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);
}
//獲取當(dāng)前字符串的二進(jìn)制

(10) 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++];
    }
}

(11)public byte[] getBytes(String charsetName)

        throws UnsupportedEncodingException {
    if (charsetName == null) throw new NullPointerException();
    return StringCoding.encode(charsetName, value, 0, value.length);
}

  
 (12)public byte[] getBytes() {

  return StringCoding.encode(value, 0, value.length);

  }
(13) 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;
}
(14)public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

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

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

   這個主要是用來比較String和StringBuffer或者StringBuild的內(nèi)容是否一樣。可以看到傳入?yún)?shù)是CharSequence ,
   這也說明了StringBuffer和StringBuild同樣是實(shí)現(xiàn)了CharSequence。源碼中先判斷參數(shù)是從哪一個類實(shí)例化來的,
   再根據(jù)不同的情況采用不同的方案,不過其實(shí)大體都是采用上面那個for循環(huán)的方式來進(jìn)行判斷兩字符串是否內(nèi)容相同。

(16)public int compareTo(String anotherString) {

    int len1 = value.length;
    int len2 = anotherString.value.length;
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
   }

   這個就是String對Comparable接口中方法的實(shí)現(xiàn)了。其核心就是那個while循環(huán),通過從第一個開始比較每一個字符,
   當(dāng)遇到第一個較小的字符時(shí),判定該字符串小。

(17)public int compareTo(String anotherString) {

    int len1 = value.length;
    int len2 = anotherString.value.length;
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}
這個就是String對Comparable接口中方法的實(shí)現(xiàn)了。其核心就是那個while循環(huán),通過從第一個開始比較每一個字符,當(dāng)遇到第一個較小的字符時(shí),判定該字符串小

(18)

 public int compareToIgnoreCase(String str) {
    return CASE_INSENSITIVE_ORDER.compare(this, str);
}
這個也是比較字符串大小,規(guī)則和上面那個比較方法基本相同,差別在于這個方法忽略大小寫

(19)public boolean regionMatches(int toffset, String other, int ooffset,

        int len) {
    char ta[] = value;
    int to = toffset;
    char pa[] = other.value;
    int po = ooffset;
    // Note: toffset, ooffset, or len might be near -1>>>1.
    if ((ooffset < 0) || (toffset < 0)
            || (toffset > (long)value.length - len)
            || (ooffset > (long)other.value.length - len)) {
        return false;
    }
    while (len-- > 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
}
比較該字符串和其他一個字符串從分別指定地點(diǎn)開始的n個字符是否相等。看代碼可知道,其原理還是通過一個while去循環(huán)對應(yīng)的比較區(qū)域進(jìn)行判斷,但在比較之前會做判定,判定給定參數(shù)是否越界。

(20) public boolean startsWith(String prefix, int toffset) {

        char ta[] = value;
        int to = toffset;
        char pa[] = prefix.value;
        int po = 0;
        int pc = prefix.value.length;
        // Note: toffset might be near -1>>>1.
        if ((toffset < 0) || (toffset > value.length - pc)) {
            return false;
        }
        while (--pc >= 0) {
            if (ta[to++] != pa[po++]) {
                return false;
            }
        }
        return true;
    }  
判斷當(dāng)前字符串是否以某一段其他字符串開始的,和其他字符串比較方法一樣,其實(shí)就是通過一個while來循環(huán)比較。

(21)public int indexOf(int ch, int fromIndex) {

        final int max = value.length;
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }

        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }

(22) public int indexOf(int ch) {

        return indexOf(ch, 0);
    }

(23) public String substring(int beginIndex) {

        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
這個方法可以返回字符串中一個子串,看最后一行可以發(fā)現(xiàn),其實(shí)就是指定頭尾,然后構(gòu)造一個新的字符串。

(24) public String concat(String str) {

        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

    concat的作用是將str拼接到當(dāng)前字符串后面,通過代碼也可以看出其實(shí)就是建一個新的字符串。

(25) public String replace(char oldChar, char newChar) {

        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }
    替換操作,主要是將原來字符串中的oldChar全部替換成newChar。看這里實(shí)現(xiàn),主要是先找到第一個所要替換的字符串的位置 i ,
    將i之前的字符直接復(fù)制到一個新char數(shù)組。然后從 i 開始再對每一個字符進(jìn)行判斷是不是所要替換的字符。

(26) public String trim() {

        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

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

    這個函數(shù)平時(shí)用的應(yīng)該比較多,刪除字符串前后的空格,原理是通過找出前后第一個不是空格的字符串,返回原字符串的該子串。

(27) public CharSequence subSequence(int beginIndex, int endIndex) {

        return this.substring(beginIndex, endIndex);
    }
    返回一個新的字符類型的字符串
    
    

本文借鑒于 https://www.cnblogs.com/liste...,情聯(lián)系刪除

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

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

相關(guān)文章

  • JDK源碼解析系列object

    摘要:在應(yīng)用程序的一次執(zhí)行到另外一次執(zhí)行,同一對象的返回的哈希碼無須保持一致。則是以對象的哈希碼為實(shí)參,以進(jìn)制無符號整數(shù)形式返回此哈希碼的字符串表示形式。 JDK源碼之Object類 1 private static native void registerNatives(); Java中,用native關(guān)鍵字修飾的函數(shù)表明該方法的實(shí)現(xiàn)并不是在Java中去完成,而是由C++去完成,并被編譯成...

    binaryTree 評論0 收藏0
  • vue-loader 源碼解析系列 selector

    摘要:當(dāng)前正在處理的節(jié)點(diǎn),以及該節(jié)點(diǎn)的和等信息。源碼解析之一整體分析源碼解析之三寫作中源碼解析之四寫作中作者博客作者作者微博 筆者系 vue-loader 貢獻(xiàn)者之一(#16) 前言 vue-loader 源碼解析系列之一,閱讀該文章之前,請大家首先參考大綱 vue-loader 源碼解析系列之 整體分析 selector 做了什么 const path = require(path) co...

    miqt 評論0 收藏0
  • java源碼

    摘要:集合源碼解析回歸基礎(chǔ),集合源碼解析系列,持續(xù)更新和源碼分析與是兩個常用的操作字符串的類。這里我們從源碼看下不同狀態(tài)都是怎么處理的。 Java 集合深入理解:ArrayList 回歸基礎(chǔ),Java 集合深入理解系列,持續(xù)更新~ JVM 源碼分析之 System.currentTimeMillis 及 nanoTime 原理詳解 JVM 源碼分析之 System.currentTimeMi...

    Freeman 評論0 收藏0
  • jvm原理

    摘要:在之前,它是一個備受爭議的關(guān)鍵字,因?yàn)樵诔绦蛑惺褂盟占骼斫夂驮矸治龊喎Q,是后提供的面向大內(nèi)存區(qū)數(shù)到數(shù)多核系統(tǒng)的收集器,能夠?qū)崿F(xiàn)軟停頓目標(biāo)收集并且具有高吞吐量具有更可預(yù)測的停頓時(shí)間。 35 個 Java 代碼性能優(yōu)化總結(jié) 優(yōu)化代碼可以減小代碼的體積,提高代碼運(yùn)行的效率。 從 JVM 內(nèi)存模型談線程安全 小白哥帶你打通任督二脈 Java使用讀寫鎖替代同步鎖 應(yīng)用情景 前一陣有個做...

    lufficc 評論0 收藏0
  • 我的阿里路+Java面經(jīng)考點(diǎn)

    摘要:我的是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)。因?yàn)槲倚睦砗芮宄业哪繕?biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來的學(xué)習(xí)計(jì)劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...

    姘擱『 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<