序文
この記事では、主にJDKソースコード分析、StringBuilder、StringBufferに関する関連コンテンツを紹介します。参照と学習のために共有されます。以下ではあまり言いません。詳細な紹介を一緒に見てみましょう。
文字列クラスのステートメント
パブリックファイナルクラスの文字列はjava.io.serializable、comparable <string>、charsequence {…}を実装しています文字列クラスは最終的な修飾子を使用して、継承できないことを示します。同時に、3つのインターフェイスを実装し、シリアル化可能なインターフェイスを実装して、文字列クラスをシリアル化できることを示します。比較可能な<t>インターフェイスを実装すると、主に文字列文字列を比較するための比較方法が提供されます。また、Charが読み取り可能なシーケンスに値することを表すCharSequenceインターフェイスも実装します(Charbuffer、Segment、String、StringBuffer、およびStringBuilderもCharSequenceインターフェイスを実装します)
文字列メインフィールドと属性の説明
/*文字列値、文字列に実際の文字を保存する*/プライベート最終char値[];/*文字列のハッシュ値デフォルト値0*/private int hash; /*文字列デフォルト値のハッシュ値0*//*文字列オブジェクトをソートするために使用されるコンパレータ、比較科のメソッドは使用します*/public static final Comparator <string> case_insensitive_order = new CaseinsensitiveComparator();
文字列部分メソッド分析
文字列クラスは一連のコンストラクターを提供し、そのうちのいくつかは、下の図に示すように、もはや推奨されません。
コンストラクタ
一般的に使用される2つのコンストラクターの実装は次のとおりです。
// string str = new String( "123")public string(string original){this.value = original.value; this.hash = original.hash;} // string str3 = new string(new char [] {'1'、 '2'、 '3'}); public string(char value []){// value = value = arrays.copyof(value、value.length); }boolean equals(オブジェクトanobject)
文字列クラスは、この文字列を指定されたオブジェクトと比較するための等しい方法をオーバーライドします。パラメーターがnullでなく、このオブジェクトと同じ文字シーケンスを表す文字列オブジェクトである場合にのみ、結果が当てはまります。
public boolean equals(object anobject){//オブジェクト参照を直接比較し、trueを返します(this == anobject){return true; } //現在のオブジェクトの文字シーケンスをAnobject値のif(anobject instanceof string){string anotherString =(string)anobject; int n = value.length; if(n == anotherstring.value.length){char v1 [] = value; char v2 [] = anothestring.value; int i = 0; while(n - != 0){if(v1 [i]!= v2 [i])false; i ++; } trueを返します。 }} falseを返します。 }int比較(string anotherstring)
2つの文字列の文字シーケンスを少しずつ比較します。少し文字が同じでない場合は、そのビットの2つの文字のユニコード値の違いを返します。すべてのビットは同じで、2つの文字列の長さの差を計算します。 2つの文字列が同じ場合は、0を返します。
public int compareto(string anothestring){int len1 = value.length; int len2 = anothestring.value.length; //長さが小さいint lim = math.min(len1、len2)で文字列の長さを取得します。 char v1 [] = value; char v2 [] = anothestring.value; int k = 0; while(k <lim){// 2つの文字列の文字シーケンス値を1つずつ比較します。等しくない場合は、その位置の2つの文字のユニコードの差をchar c1 = v1 [k]に返します。 char c2 = v2 [k]; if(c1!= c2){return c1 -c2; // unicode} k ++の差を返します。 } //小さな文字列のすべてのビットが比較され、2つの文字列の長さの差が返されます// 2つの文字列が同じ場合、長さの差は0です。 } CompareToignOreCase(String Str)メソッドも同様に実装されています。キャラクターの上限と小文字は比較中に無視され、実装方法は次のとおりです。
public int compare(string s1、string s2){int n1 = s1.length(); 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){c1 = character.touppercase(c1); C2 = Character.Touppercase(C2); if(c1!= c2){c1 = character.tolowercase(c1); C2 = Character.TolowerCase(C2); if(c1!= c2){//数値プロモーションのためにオーバーフローはありませんc1 -c2; }}}} n1 -n2を返します。 }ネイティブストリングインターン()
インターンメソッドが呼び出されると、プールにこの文字列オブジェクトに等しい文字列が既に含まれている場合(equals(オブジェクト)メソッドで決定)、プール内の文字列が返されます。それ以外の場合は、この文字列オブジェクトをプールに追加し、この文字列オブジェクトへの参照を返します。
すべてのリテラル文字列および文字列割り当て定数式は、INTERメソッドを使用して動作します。たとえば、string str1 = "123"。
文字列メモリの場所:一定のプールまたはヒープ
文字列オブジェクトは、リテラルまたはコンストラクターを介して直接作成できます。違いは何ですか?
1。「+」スプライシングを通る文字通りまたはリテラル文字列によって作成された文字列オブジェクトは、一定のプールに保存されます。実際の作成中に一定のプールが存在する場合、参照は直接返されます。存在しない場合、文字列オブジェクトが作成されます。
2。コンストラクターを使用して文字列オブジェクトを作成し、ヒープに直接文字列オブジェクトを作成します
3.インターンメソッドを呼び出し、オブジェクトを返すオブジェクトは定数プールに入れられます(存在しない場合は、定数プールに配置され、存在する場合、参照に返されます)
以下は、文字列オブジェクトのメモリ割り当ての例です。
string str1 = new String( "123");文字列str2 = "123";文字列str3 = "123"; string str4 = str1.intern(); System.out.println(str1 == str2); // false str1ヒープ内でオブジェクトを作成し、str2は定数プールsystem.out.println(str2 == str3)にオブジェクトを作成します。 // true str2は定数プールにオブジェクトを作成し、str3はstr2によって作成されたオブジェクトへの参照を直接返します。これにより、str2とstr3は定数プールシステムの同じオブジェクトを指します。out.println(str4 == str3); // True Str4は、定数プールに「123」の値を持つオブジェクトを返します。したがって、Str4、Str2、およびStr3は等しくなります。
文字列ステッチの例について:
public class stringtest {public static final string x = "abc"; // constant x @test public void test(){string str5 = new String( "ABC"); string str6 = str5+"def"; // string str7 = "abc"+"def"を作成します。 //定数プール文字列str8 = x+"def"; // xは定数であり、値は固定されているため、x+"def"の値はABCDEFに設定されています。実際、コンパイル後、コードはstring str8 = "abcdef" string str9 = "abc"に相当します。文字列str10 = str9+"def"; //system.out.println(str6==str7); // false system.out.println(str8 == str7); // true System.out.println(str10 == str7); // false system.out.println(x == str9); //真実} }分解されたコードは一目で明らかになります:
メモリの割り当ては次のとおりです。
文字列、stringbuffer、stringbuilder
ストリングタイプによって内部に維持されている文字列を保存するためのプロパティ値[]文字配列は、最終的に変更されます。
/**値は文字ストレージに使用されます。 */プライベートファイナルチャーバリュー[];
割り当て後に変更できることを示しています。したがって、文字列オブジェクトは作成されると不変であると考えています。開発中に頻繁にスプライシング文字列操作に遭遇した場合、文字列で提供される連絡先を使用する場合、または「+」スプライシングストリングを直接使用する場合、新しい文字列が頻繁に生成されます。 Javaは他の2つのクラスを提供します。StringBufferとStringBuilderは、この問題を解決するために使用されます。
次のコードを見てください。
文字列str1 = "123";文字列str2 = "456";文字列str3 = "789"; string str4 = "123" + "456" + "789"; //定数を追加すると、コンパイラは文字列str4 = "123456789" string str5 = str1 + str2 + str3を自動的に認識します。 //スタンド文字列変数スプライシング、stringbuilder stringbuilder sb = new StringBuilder()を使用することをお勧めします。 sb.append(str1); sb.append(str2); sb.append(str3);
以下は、分析されたコードの一部のみを傍受するStringBuilderクラスの実装です。
パブリックファイナルクラスStringBuilderは、AbstractStringBuilderを拡張しますJava.io.Serializable、CharSequence {// Split String @Override public StringBuilder append {// Parent Class AbstractStringBuilder.Append Super.Append(STR);これを返します。 }}抽象クラスの要約ストリングビルダーは、文字列の型とは異なる文字列* / char []値とは異なる文字列を格納する文字アレイ、charsequence { / *** appendable、charsequence { / ***を実装しています。 /***カウントは使用される文字の数です。 */ int count; public AbstractStringBuilder append(string str){if(str == null)return appendnull(); int len = str.length(); //容量を拡張する必要があるかどうかを確認します。 // string strをvalueにコピーしますstr.getchars(0、len、value、count); count += len;これを返します;} private void ensurecapacityinternal(int mosticalcapacity){// overflow -conscious code // minimutcapacity = count+str.length // strがスプライスされた容量が値容量よりも大きい場合、if(minimutcapacity -value.length> 0){//容量を拡大する容量=拡大値をコピーします。 arrays.copyof(value、newcapacity(minimutcapacity)); }} // StringBuilder拡張Private int NewCapacity(int mincapacity){//オーバーフロー - 意識コード//拡張容量の計算//デフォルトの拡張配列の長さは、元の数(値[])グループの長さの2倍拡張され、2がルールに追加されます。なぜ2つ追加するのですか? int newcapacity =(value.length << 1) + 2; if(newcapacity -mincapacity <0){newcapacity = mincapacity; } return(newcapacity <= 0 || max_array_size -newcapacity <0)? hugecapacity(mincapacity):Newcapacity; }}StringBufferとStringBuilderにも同じことが言えます。内部的に維持される値[]文字配列は可変です。唯一の違いは、StringBufferがスレッドセーフであることです。すべてのメソッドを同期します。 StringBuilderはスレッドではありません。したがって、マルチスレッド操作と文字列変数の共有の場合、文字列スプライシング処理には弦楽剤が推奨されます。それ以外の場合、StringBuilderを使用できます。結局のところ、スレッドの同期も特定の消費をもたらします。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。