ホームページ  >  記事  >  Java  >  String ソースコードの解釈例

String ソースコードの解釈例

零下一度
零下一度オリジナル
2017-06-29 09:55:321472ブラウズ

String クラスは、文字列を格納するために char[] 型の値を内部的に保持します。ソース コードは比較的単純です。

1. 不変性

String の不変性は主に 3 つの側面に反映されます:

  • String クラスは Final 型として定義されており、継承できません

  • String の value[] は Final として定義されています

  • String で新しい String を生成するすべての操作は、Array.copy または System.copy を呼び出して、新しい String オブジェクトを生成します。 2. Constructor、String のコンストラクターは比較的単純ですが、以下はさらに特殊です

        public String(String original) {
            this.value = original.value;
            this.hash = original.hash;
        }
        
        String(char[] value, boolean share) {
            // assert share : "unshared not supported";
            this.value = value;
        }
  • 上の 2 つは、比較的特殊なタイプのコンストラクター。最初のコンストラクターは、既製の String を使用して新しい String オブジェクトを初期化し、新しい String オブジェクトの値を古い値オブジェクトに直接指します。 String は不変であるため、ここで値オブジェクトを再コピーする必要はありません。 2 番目のコンストラクターは String 型の不変性を破壊しているように見えます (パラメーター値が変更されると String も変更されます)。ただし、このコンストラクターは public として宣言されておらず、 String() が public として宣言されているパッケージ内でのみ使用できます。 char value[]) 基になる呼び出しは、基になるデータのコピーを実現するための Array.copy です。上記の 2 つのコンストラクターの使用は推奨されなくなりました
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
上記のコンストラクターはより一般的であり、他の多くのコンストラクターはこれに類似しているか、基になるコンストラクターと同様です。 call このコンストラクターを呼び出す場合、入力パラメーターは char 配列 (byte[])、offset offset 位置、および count offset です。最下層は Arrays.copy 関数を呼び出してディープ コピーを実行します。
    public String(StringBuffer buffer) {
        synchronized(buffer) {  //保证线程安全
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
    
    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }

上記 2 つのコンストラクターの入力パラメーターはそれぞれ StringBuffer と StringBuilder で、最下層は Arrays.copyOf を呼び出します。唯一の違いは、StringBuffer がスレッドセーフであり、すべての呼び出しで synchronized キーワードを使用する必要があることです。

3. その他のメソッド

    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        if (fromIndex >= sourceCount) {
            return (targetCount == 0 ? sourceCount : -1);
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {
            return fromIndex;
        }

        char first = target[targetOffset];
        int max = sourceOffset + (sourceCount - targetCount);

        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }

            /* Found first character, now look at the rest of v2 */
            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;
                }
            }
        }
        return -1;
    }
    
    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        /*
         * Check arguments; return immediately where possible. For
         * consistency, don&#39;t check for null str.
         */
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0) {
            return -1;
        }
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }
        /* Empty string always matches. */
        if (targetCount == 0) {
            return fromIndex;
        }

        int strLastIndex = targetOffset + targetCount - 1;
        char strLastChar = target[strLastIndex];
        int min = sourceOffset + targetCount - 1;
        int i = min + fromIndex;

        startSearchForLastChar:
        while (true) {
            while (i >= min && source[i] != strLastChar) {
                i--;
            }
            if (i < min) {
                return -1;
            }
            int j = i - 1;
            int start = j - (targetCount - 1);
            int k = strLastIndex - 1;

            while (j > start) {
                if (source[j--] != target[k--]) {
                    i--;
                    continue startSearchForLastChar;
                }
            }
            return start - sourceOffset + 1;
        }
    }

indexOf と lastIndexOf は、主に、index 関数と lastIndex 関数の基礎となる呼び出しであることがわかりますが、基礎となる実装には、依然として、特に強力な kmp アルゴリズムが実装されています。文字ごとにスキャンします。その中で、lastIndexOf は依然として continue startSearchForLastChar; を使用していますが、これは比較的まれです。

    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;
                }
            }
            //如果找不到则返回this
            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++;
                }
                //返回新的String,利用上述包内的非public构造函数
                return new String(buf, true);
            }
        }
        return this;
    }
replace は、String オブジェクト内の 1 つの文字を別の文字に置き換えるのに使用されます。指定された文字が見つからない場合は、それ自体を返します。見つかった場合は、新しい String オブジェクトを作成して返します。

---リカバリコンテンツの終了---

以上がString ソースコードの解釈例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。