StringとStringBufferの少しの研究
4552 ワード
転載元:http://www.cnblogs.com/heshan664754022/archive/2013/03/15/2961463.html
まず下のこれらの出力の結果を見てください。ゆっくり考えてください。そんなに速く答えないでください。
false true false false true
ここで詳しく分析してみます。まず最初です。
この問題を見る時、まず以下の原理的な説明を見てください。
String s=new String(「aaa」)
1) まず、String Poolで「aaa」という文字列のオブジェクトがあるかどうかを調べます。もしあるなら、String Poolで「aaa」というオブジェクトを作成しません。直接にヒープの中に「aaa」という文字列のオブジェクトを作成して、この「aa」のオブジェクトの住所を戻して、s参照を作成します。文字列オブジェクト
2) もしないならば、まずString Poolの中で一つの「aa」オブジェクトを作成し、その後、ヒープの中で一つの「aaa」オブジェクトを作成し、その後、ヒープの中のこれを「aa」オブジェクトのアドレスを返して、s参照を与えて、これをヒープの中で作成した「aa」オブジェクトにsを指します。
上記の説明を見て、分かりましたよね。strとstr 2はそれぞれ山の中の違う対象を指しています。だから住所が違っています。結局falseです。
そして二つ目
String str 3 = 「bb」;(額面による値付け)
1) String Poolに「bb」というオブジェクトが存在するかどうかを調べ、存在しない場合は、String Poolに「bb」オブジェクトを作成し、String Poolのこの「bb」オブジェクトのアドレスを返して参照変数str 3に割り当てられる。 ,このようにstr 3 StringPoolのこの「bb」文字列のオブジェクトを指します。
2) 存在する場合は、いかなるオブジェクトも作成せずに、String Poolのこの「bbb」オブジェクトアドレスを直接にstr 3に返信します。 参照
見終わった後で信じてもいいです。str 3とstr 4は同じ相手の住所を指しています。結果はもちろんtrueです。
それから三つ目です。前の二つが分かったら、三つ目は私が何も言わなくてもいいと信じています。もし分からなかったら、先に二つのことを分かってください。
今から四番目に見に来ます。
Stringは、作成が完了するとオブジェクトが変更できなくなります。+スティッチング文字列を使用すると、元のStringオブジェクトにコンテンツを追加するのではなく、新しいStringオブジェクトが生成されます。
だからs 1+s 2の時に、実はヒープの中で新たに新しいオブジェクトを作ったので、s 1+s 2の住所とは違います。
最後の問題について
System.out.println(s==「hel」+「lo」)
私の理解はJVMが文字列の定数の「+」に接続してプログラムをコンパイルします。
JVMは定数文字列の「+」接続を接続後の値に最適化し、「hel」+「lo」を使ってコンパイラを最適化した後、classではハローである。
コンパイル期間に文字列定数の値が確定し、文字列定数プールに保存されますので、上のプログラムの最終的な結果はtrueです。
Stringbufferのテーマを添付します。
スタックには元のデータタイプの局所変数データやオブジェクトの参照(String,配列.オブジェクトなど)が格納されていますが、オブジェクトの内容は保存されていません。
newキーワードを使って作成したオブジェクトをヒープに保存します。
文字列は特殊な包装類で、参照はスタックに保存されています。オブジェクトの内容は作成方法によって決められています。コンパイル期間によって作成されたものもあります。文字列の常量池に保存されています。実行時に作成されるものもあります。newキーワードを使ってヒープに保存します。状況によって判断します。原理を理解すれば、似たような問題が解決されます。
まず下のこれらの出力の結果を見てください。ゆっくり考えてください。そんなに速く答えないでください。
String str =
new
String(
"aaa"
);
String str2 =
new
String(
"aaa"
);
System.out.println(str == str2);
System.out.println(
"----------------"
);
String str3 =
"bbb"
;
String str4 =
"bbb"
;
System.out.println(str3 == str4);
System.out.println(
"----------------"
);
String str5 =
new
String(
"ccc"
);
String str6 =
"ccc"
;
System.out.println(str5 == str6);
System.out.println(
"----------------"
);
String s =
"hello"
;
String s1 =
"hel"
;
String s2 =
"lo"
;
System.out.println(s == s1 + s2);
System.out.println(
"----------------"
);
System.out.println(s ==
"hel"
+
"lo"
);
ここに来たらあなたが答えを出したと信じています。正しい結果は:false true false false true
ここで詳しく分析してみます。まず最初です。
String str =
new
String(
"aaa"
);
String str2 =
new
String(
"aaa"
);
System.out.println(str == str2);
この問題を見る時、まず以下の原理的な説明を見てください。
String s=new String(「aaa」)
1) まず、String Poolで「aaa」という文字列のオブジェクトがあるかどうかを調べます。もしあるなら、String Poolで「aaa」というオブジェクトを作成しません。直接にヒープの中に「aaa」という文字列のオブジェクトを作成して、この「aa」のオブジェクトの住所を戻して、s参照を作成します。文字列オブジェクト
2) もしないならば、まずString Poolの中で一つの「aa」オブジェクトを作成し、その後、ヒープの中で一つの「aaa」オブジェクトを作成し、その後、ヒープの中のこれを「aa」オブジェクトのアドレスを返して、s参照を与えて、これをヒープの中で作成した「aa」オブジェクトにsを指します。
上記の説明を見て、分かりましたよね。strとstr 2はそれぞれ山の中の違う対象を指しています。だから住所が違っています。結局falseです。
そして二つ目
String str3 =
"bbb"
;
String str4 =
"bbb"
;
System.out.println(str3 == str4);
その前に、私達も先に原理的な説明を見ます。String str 3 = 「bb」;(額面による値付け)
1) String Poolに「bb」というオブジェクトが存在するかどうかを調べ、存在しない場合は、String Poolに「bb」オブジェクトを作成し、String Poolのこの「bb」オブジェクトのアドレスを返して参照変数str 3に割り当てられる。 ,このようにstr 3 StringPoolのこの「bb」文字列のオブジェクトを指します。
2) 存在する場合は、いかなるオブジェクトも作成せずに、String Poolのこの「bbb」オブジェクトアドレスを直接にstr 3に返信します。 参照
見終わった後で信じてもいいです。str 3とstr 4は同じ相手の住所を指しています。結果はもちろんtrueです。
それから三つ目です。前の二つが分かったら、三つ目は私が何も言わなくてもいいと信じています。もし分からなかったら、先に二つのことを分かってください。
今から四番目に見に来ます。
String s =
"hello"
;
String s1 =
"hel"
;
String s2 =
"lo"
;
System.out.println(s == s1 + s2);
この問題を見る時、私たちは同じ原理的な説明を見ます。Stringは、作成が完了するとオブジェクトが変更できなくなります。+スティッチング文字列を使用すると、元のStringオブジェクトにコンテンツを追加するのではなく、新しいStringオブジェクトが生成されます。
だからs 1+s 2の時に、実はヒープの中で新たに新しいオブジェクトを作ったので、s 1+s 2の住所とは違います。
最後の問題について
System.out.println(s==「hel」+「lo」)
私の理解はJVMが文字列の定数の「+」に接続してプログラムをコンパイルします。
JVMは定数文字列の「+」接続を接続後の値に最適化し、「hel」+「lo」を使ってコンパイラを最適化した後、classではハローである。
コンパイル期間に文字列定数の値が確定し、文字列定数プールに保存されますので、上のプログラムの最終的な結果はtrueです。
Stringbufferのテーマを添付します。
StringBuffer sb1 =
new
StringBuffer(
"hello"
);
StringBuffer sb2 =
new
StringBuffer(
"hello"
);
System.out.println(sb1.equals(sb2));
true , StringBuffer equals , Object equals , , false 。
まとめ:上のいくつかの問題が分かったら、String類に対してもっと深い認識ができたと信じています。スタックには元のデータタイプの局所変数データやオブジェクトの参照(String,配列.オブジェクトなど)が格納されていますが、オブジェクトの内容は保存されていません。
newキーワードを使って作成したオブジェクトをヒープに保存します。
文字列は特殊な包装類で、参照はスタックに保存されています。オブジェクトの内容は作成方法によって決められています。コンパイル期間によって作成されたものもあります。文字列の常量池に保存されています。実行時に作成されるものもあります。newキーワードを使ってヒープに保存します。状況によって判断します。原理を理解すれば、似たような問題が解決されます。