StringとStringBufferの少しの研究

4552 ワード

転載元:http://www.cnblogs.com/heshan664754022/archive/2013/03/15/2961463.html
まず下のこれらの出力の結果を見てください。ゆっくり考えてください。そんなに速く答えないでください。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キーワードを使ってヒープに保存します。状況によって判断します。原理を理解すれば、似たような問題が解決されます。