1.文字列の概要、共通のメソッドソースコード分析
2。文字列定数プール分析
一般的な方法
平等です
トリム
交換する
concat
スプリット
StartswithとEndswith
サブストリング
touppercase()およびtolowercase()
比較
文字列の紹介
文字列クラスはファイナルによって変更されます。つまり、文字列オブジェクトは不変であり、同時プログラムが不変を好むことを意味します。文字列クラスは、シリアル化可能な、同等の、充電インターフェイスを実装します。
コードから始めます:
public void stringtest(){string a = "a"+"b" +1;文字列b = "ab1"; System.out.println(a == b);}結果は何だと思いますか?あなたの結論が真実なら。 OK、別のコードを持ってみましょう:
public void stringtest(){string a = new String( "ab1");文字列b = "ab1"; System.out.println(a == b);}結果は何ですか?正解は偽です。
コンパイラによってコンパイルされたコードを見てみましょう
//最初のコードpublic void stringtest(){string a = "ab1";文字列b = "ab1"; System.out.println(a == b);} // 2番目のコードpublic void stringtest(){string a1 = new String( "ab1");文字列b = "ab1"; System.out.println(a1 == b);}言い換えれば、コンパイル期間中に最初のコードは最適化されています。これは、「A」+"b" +1と「ab1」の効果が同じであり、どちらも不変で構成されていることをコンパイラが発見したためです。しかし、なぜ彼らのメモリアドレスは同じですか?まだこれに興味がある場合は、文字列クラスのいくつかの重要なソースコードを見てみましょう。
ソースコード
1。文字列属性
文字列クラスには、文字列を保存する不変のcharアレイが含まれており、計算されたハッシュ値を保存するためにint変数ハッシュが使用されます。
/**値は文字ストレージに使用されます。 */private final char value [];/**文字列のハッシュコードをキャッシュ*/private int hash; //デフォルトで0/** JDK 1.0.2のSerialVersionUidを使用して、相互運用性には*/private static final long serialversionuid = -6849794470754667710L;
2。文字列コンストラクター
//パラメーターのないコンストラクターは一般に役に立たない。値は不変のpublic string(){this.value = new char [0];} //パラメーターは文字列型public string(string original){this.value = original.value; this.hash = original.hash;} //パラメーターはchar配列です。java.utilsパッケージの配列クラスを使用してpublic string(char value []){this.value = arrays.copyof(value、length);} // bytes restes and abult name(charpubl string)and abult name sting in string(charp、copyof(value、length);} //) BYTES []、int offset、int length、string charsetname)unsupportedencodingException {if(charsetname == null)スローnew nullpointerexception( "charsetname");チェックバウンド(バイト、オフセット、長さ); this.value = stringCoding.decode(charsetname、bytes、offset、length);} // public string(byte bytes []、int offset、int length、string charsetname)コンストラクターパブリック文字列(バイトバイト[]、文字列charsetname)を通話3。文字列の一般的な方法
1。等しい
booleanは等しい(オブジェクトanobject)public boolean equals(object anobject){//参照が同じオブジェクトの場合、trueを返します(this == anobject){return true; } //型文字列のデータが文字列ではない場合、falseを返します(anobject instanceof string){string anothestring =(string)anobject; int n = value.length; // char配列の長さが等しくない場合、if(n == anotherstring.value.length){char v1 [] = value; char v2 [] = anothestring.value; int i = 0; //単一の文字から正面に戻る判断、不平等がある場合、falseを返しますwith(n - != 0){if(v1 [i]!= v2 [i])falseを返します。 i ++; } //各文字は等しく、trueを返すtrueを返します。 }} false;}string e1 = "good"; string e2 = "good enaly"; e1.equals(e2); // falseを返します
1最初に、同じオブジェクトが参照されるかどうかを決定します。つまり、2つの参照のメモリアドレスが同じかどうかを決定します。同じ場合、それは直接trueを返します。
2は、タイプが同じかどうか、およびそれらが同じデータ型であるかどうかを決定します
3同じタイプを使用する場合、変換された文字配列の長さは同じです。
4各文字が背面から正面まで同じかどうかを比較します
判断順序= 》1。メモリアドレス2。データ型3。文字配列長4。単一文字比較
2。比較
int compareto(string anotherstring)public int compareto(string anotherstring){//独自のオブジェクトの文字列の長さlen1 int len1 = value.length; //比較オブジェクトの文字列の長さlen2 = anothestring.value.length; // 2つの文字列の長さの最小値lim int lim = math.min(len1、len2); char v1 [] = value; char v2 [] = anothestring.value; int k = 0; //値の最初の文字から最小長limまで、文字が等しくない場合、それ自体を返します(オブジェクトが等しくない文字 - 比較される文字)while(k <lim){char c1 = v1 [k]; char c2 = v2 [k]; if(c1!= c2){return c1 -c2; } k ++; } //フロントがすべて等しい場合、return(それ自体が比較されるオブジェクトの長さ - )戻りlen1 -len2;}string co1 = "hello"; string co2 = "hello"; string co3 = "hello you"; System.out.println(co1.compareto(co2)); // 0system.out.println(co1.compareto(co3)); // -4
この方法は巧妙に記述されており、最初に0から文字サイズを判断できます。
2つのオブジェクト間の比較が文字を比較できる場合、比較されるオブジェクトの長さが直接返されます。 2つの文字列の長さが等しい場合、リターンは0であり、3つの状況を巧みに判断します。
3.HashCode
int hashcode()public int hashcode(){int h = hash; //ハッシュが計算されておらず、文字列が空でない場合、ハッシュコード計算が実行されます(h == 0 && value.length> 0){char val [] = value; //計算プロセス// s [0]*31^(n-1) + s [1]*31^(n-2) + ... + s [n-1] for(int i = 0; i <value.length; i ++){h = 31*h + val [i]; } //ハッシュ割り当てhash = h; } return h;}string a = "toyou"; char val [] = a.tochararray(); char c1 = 't'; char c2 = 'a'; int f = c1; int e = c2; System.out.println(e); // 97 asystem.out.println(f); // 116 tsystem.out.println(31*val [0]); // 3596system.out.println(31*c1); // 3596 //ハッシュコード計算CHAR文字を対応するINTシェーピングに自動的に変換できるため
文字列クラスはハッシュコードメソッドをオーバーライドし、オブジェクトのハッシュコードメソッドはネイティブコールです。
文字列クラスのハッシュは、多項式を使用して計算されます。異なる文字列を通して同じハッシュを完全に取得できます。したがって、2つの文字列オブジェクトのハッシュコードは同じですが、これは2つの文字列が同じであることを意味しません。
同じ文字列オブジェクトのハッシュコードは同じでなければなりませんが、ハッシュコードは同じであり、必ずしも同じオブジェクトではありません
4.Startswith
boolean startswith(string prefix、int toffset)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; //注:toffsetは-1 >>>に近い場合があります。 //開始アドレスが0未満または(recumentオブジェクトの開始アドレス +長さ)が独自のオブジェクトの長さより大きい場合、falseを返します((toffset <0)||(toffset> value.length -pc)){return false; } //比較されるオブジェクトの端から比較されるwhile(--pc> = 0){if(ta [to ++]!= pa [po ++]){return false; }} return true;} public boolean startswith(string prefix){return startswith(prefix、0);} public boolean endswith(string suffix){return startswith(suffix、value.length -length -length -value.length);}}文字列d = "www.58fxp.com"; System.out.println(d.startswith( "www")); // true System.out.println(d.endswith( "com")); // 真実
開始と終了の比較は一般的な方法です。たとえば、文字列がHTTPプロトコルからであるかどうかを判断する場合、またはファイルがMP3ファイルであるかどうかを最初に判断する場合、この方法を使用して比較できます。
5.CONCAT
string concat(string str)public string concat(string str){int otherlen = str.length(); //追加された文字列が空の場合、(otherlen == 0){これを返します。 } int len = value.length; char buf [] = arrays.copyof(value、len + otherlen); str.getchars(buf、len);新しい文字列(buf、true);}string cat = "much";文字列newcat = cat.concat( "yes"); //はい
concatメソッドは、一般的に使用される方法の1つでもあります。最初に、追加された文字列が空であるかどうかを判断して、新しいオブジェクトを作成するかどうかを決定します。
1スプライスされた文字の長さが0の場合は、元の文字オブジェクトに直接返します
2スプライスされた文字は空ではなく、新しい文字オブジェクトを返します
文字の長さを決定して、新しいオブジェクトを生成します
6.複製
文字列置換(char oldchar、char newchar)public string leplage(char oldchar、char newchar){//古い値と新しい値を最初に比較するif(oldchar!= newChar){int len = value.length; int i = -1; char [] val = value; / * GetField OpCodeを避けてください */ //古い値が最初に表示される位置を見つけます(++ i <len){if(val [i] == oldchar){break; }} //その位置から、最後まで、(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 ++; } new String(buf、true)を返します。 }}これを返します;}文字列r1 = "どうしますか"; string r2 = r1.replace( "do"、 "is"); system.out.println(r2); //お元気ですか
この方法には、最初の価値がどこに表示されるかを見つけるなど、いくつかの賢さもあり、比較時間を節約します。
交換(String Oldstr、String Newtr)メソッドは、正規表現で審査されます。
7.Trim
string trim()public string trim(){int len = value.length; int st = 0; char [] val = value; / * getfield opcodeを避けます */ //文字列の前に空間がない位置を見つけますwhile(st <len)&&(val [st] <= '')){st ++; } //文字列の端に空間のない位置を見つけますwhile(st <len)&&(val [len-1] <= '')){len--; } //正面にスペースがなく、後にスペースがない場合、文字列自体((st> 0)||(len <value.length))を返しますか?サブストリング(st、レン):this;}文字列T1 = "public void"; //正面の1つのスペースとsystem.out.println( "t1:"+t1.length()); // 13スペース長い文字列t2 = t1.trim(); System.out.println( "t2:"+t2.length()); // 11 Space System.out.println(T2)を削除します。
8.インターン
文字列インターン()public Native String Intern();
文字列dd = new String( "BB")。intern();
Nternメソッドはネイティブコールであり、その機能は、メソッド領域の定数プールの等しいメソッドを介して等しい値のオブジェクトを見つけることです。
見つからない場合は、一定のプールにスペースを開いて文字列を保存し、対応する文字列への参照を返します。それ以外の場合、文字列オブジェクトへの参照を直接返します。一定のプールには既に存在します。
また、新しい方法で作成された文字オブジェクトを強制して、定数プールが既に存在するかどうかを確認することもできます。
はじめに2番目のコードを配置します
// string a = new string( "ab1"); // string a = new String( "ab1")。
結果は、Aによって指されたアドレスが定数プールから来ており、bが指す定数はデフォルトでこの方法を呼び出すため、AとBは両方とも同じアドレス空間を指します。
int hash32()private transhhash32 = 0; int hash32(){int h = hash32; if(0 == h){// Hash32での無害なデータレースはこちら。 h = sun.misc.hashing.murmur3_32(hashing_seed、value、0、value.length); //結果がゼロでないことを確認して、h =(0!= h)の再計算を避けますか? H:1; hash32 = h; } return h;}JDK1.7では、文字列クラスがキーとして使用される場合、ハッシュ関連のコレクションクラスはハッシュコード法をデータに分離するのではなく、Hash32メソッドを使用します。
この方法では、システムの現在の時刻、文字列クラスアドレス、システムクラスアドレスなどを使用して、ハッシュシードを計算する要因として使用します。ハッシュシードを介して、ハッシュシードを介して32ビットのINT値が取得されます。
public int length(){return value.length;} public string toString(){return this;} public boolean isempty(){return value.length == 0;} public char charat(int <0)||(index> = value.length)){show newindexofbundsexception(index); } return値[index];}上記は、いくつかの単純な一般的な方法です。
要約します
文字列オブジェクトは不変のタイプです。 returnメソッドは、戻る新しい文字列オブジェクトが返されるたびに戻るたびに戻ります。
文字列オブジェクトを比較する3つの方法:
==メモリの比較:正確で簡潔で、簡単な2つの参照によって指されたメモリ値を直接比較します。
等しい文字列値の比較:2つの参照されるオブジェクトのリテラル値が等しいかどうかを比較します。
ハッシュコード文字列の比較数値化:文字列の数値化。参照される2つのハッシュコードは同じであり、メモリは同じであることが保証されておらず、リテラル値は同じであることを保証しません。
文字列定数プールのデザインアイデア
1.文字列定数プール設計の元の意図
各文字列は文字列オブジェクトであり、文字列はシステム開発で頻繁に使用されます。他のオブジェクトのように作成および破壊された場合、プログラムのパフォーマンスに大きく影響します。
パフォーマンスを改善し、メモリオーバーヘッドを減らすために、JVMは文字列をインスタンス化するときに最適化します。
キャッシュ領域と同様に、文字列定数プールが文字列用に開かれています
文字列定数を作成するとき、最初に文字列定数プールが存在するかどうかを判断します。
文字列は参照されるインスタンスを返し、存在せず、文字列をインスタンス化し、プールに入れます。
基本を実現します
この最適化を実装する根拠は、各文字列定数が最終的な変更定数であるため、定数プールのデータ競合を心配する必要はないことです。
ランタイムインスタンスによって作成されたグローバルストリング定数プールにはテーブルがあります。これは、プール内の各一意の文字列オブジェクトの参照を常に維持しています。つまり、弦の定数プール内のオブジェクトを常に参照するため、一定のプールのこれらの文字列はゴミコレクターによって収集されません。
ヒープ、スタック、メソッドエリア
文字列の定数プールを理解する、まずスタックメソッド領域を見てください
ヒープ
保存されているのはオブジェクトで、各オブジェクトには対応するクラスが含まれています
JVMには1つのヒープ領域のみがあり、すべてのスレッドで共有されています。ヒープには基本的なタイプとオブジェクトの参照はありませんが、オブジェクト自体のみがあります
オブジェクトはゴミコレクターによって収集されるため、サイズとライフサイクルを決定する必要はありません
スタック
各スレッドには、基本的なデータ型オブジェクトとカスタムオブジェクト参照のみを保存するスタック領域が含まれています。
各スタックのデータ(プリミティブタイプとオブジェクト参照)はプライベートです
スタックは、基本型変数領域、実行環境コンテキスト、および操作命令領域(操作手順の保存)の3つの部分に分割されます。
データサイズとライフサイクルは確実であり、このデータを参照しない場合、データは消えます。
メソッド領域
ヒープのような静的ゾーンは、すべてのスレッドで共有されます
メソッド領域には、クラスや静的変数など、プログラム全体で常にユニークな要素が含まれています。
文字列定数プール
文字列定数プールはメソッド領域に存在します
コード:Stack Methodエリアストリングは文字列を保存します
string str1 = "abc"; string str2 = "abc"; string str3 = "abc"; string str4 = new string( "abc"); string str5 = new string( "abc");
インタビューの質問
string str4 = new String( "ABC")作成されたオブジェクトはいくつですか?
分割:str4 =、new String()、 "ABC"
新しい方法を使用して新しいオブジェクトを作成できます。新しい方法はインスタンス化されたオブジェクトを作成し、既に存在するかどうかを見つけるために一定のプールに移動しません。新しい限り、新しいオブジェクトがインスタンス化されます。
「ABC」各文字列は文字列オブジェクトです。定数プールにない場合、新しいオブジェクトが作成され、定数プールに配置されます。それ以外の場合、オブジェクト参照が返されます。
オブジェクトアドレスをSTR4に割り当て、参照を作成します
したがって、定数プールにリテラルがない場合は、2つのオブジェクトを作成し、1つのオブジェクトを作成し、参照を作成します
string str1 = new String( "a"+"b");いくつのオブジェクトが作成されますか? string str2 = new String( "ABC") + "ABC";いくつのオブジェクトが作成されますか?
Java文字列ソースコードと文字列定数プールの上記の包括的な分析は、私があなたと共有するすべてのコンテンツです。参照を提供できることを願っています。wulin.comをもっとサポートできることを願っています。