Java Stringの知識点

6583 ワード

1.このプログラムの結果は何ですか.
private static void test1() {
  String a = "a" + "b" + 1;
  String b = "ab1";
  System.out.println(a == b);
}

 
実行結果:
true
どうしてですか.
a参照は直接付与され、b参照は「+」で付与され、aとbの2つの参照はなぜ同じものを指すのか.
個のメモリユニット?これがJVMの「コンパイル時最適化」
コンパイラがコードをコンパイルするとき:String a=“a”+“b”+1;を選択すると、String a="ab 1";にコンパイルされます.
どうして?いずれも「定数」なので、コンパイラはこの3つの定数を重ねると一定の値が得られ、実行時に再び
計算を行うので、このように最適化されます.
 
"=="について
まず「===」がメモリセルの内容にマッチするために使われていることを知っておく必要があります.実は数字で、コンピュータの内部も
数字がありますが、Java言語では「==」が一致すると、実は2つのメモリセルの内容が同じかどうかを比較します.
元のタイプbyte、boolean、short、char、int、long、float、doubleであれば、直接比較です
値を入力します.これはみんな知っているはずだが,ここではもう詳しく話さない.
リファレンス(Reference)であれば、比較するのがリファレンスの値であり、「リファレンスの値」はオブジェクトの論理とみなすことができる
住所を集める.2つの参照に「==」操作が発生した場合、対応する2つのオブジェクトのアドレス値が同じかどうかを比較します.かえる
すなわち、2つの参照が保存されているオブジェクトが同じオブジェクトである場合、trueが返され、そうでない場合falseが返されます(
参照はnullを指しますが、これもJVMが与えた指定された値です).
寓意を理解する:みんなはそれぞれ1つの会社のofferを手に入れて、今私达はどんな人が手に入れたofferが同じであることを见てみます
会社のです.
 
「equals()」について
equals()メソッドは,まずObjectクラスで定義され,その定義では"=="方式でマッチングされる.
の(この点みんなはObject類のソースコードを参照することができます).つまりequals()メソッドを書き直さなければ
対応するクラスの親リストにequals()メソッドが書き換えられていない場合、デフォルトのequals()操作は対比オブジェクトのアドレスです.
equals()メソッドが存在するのは,サブクラスがこのメソッドを書き換え,コントラスト値の機能を実現することを望んでいるからである.
Stringは自分でequals()メソッドを実現した.どうして自分で実現するの?二つの対象は具体的な仕事によって
トランザクションのキー属性値を比較して、それらが「一致または類似」であるかどうかを決定し、true|falseを返します.
 
2. このプログラムの結果は何ですか.
private static String getA() {return"a";}
public static void test2() {
String a = "a";
final String c = "a";
String b = a + "b";
String d = c + "b";
String e = getA() + "b";
String compare = "ab";
System.out.println(b == compare);
System.out.println(d == compare);
System.out.println(e == compare);
}

 
結果:
false
true
false
 
1番目の出力false.
「b」は「compare」と比較され、コードリスト1-2の解釈によれば、compareは定数であり、b
どうしてそうじゃないの?b=a+「b」のため、aは定数ではありません.aは局所変数としても、
定数ですが、参照に「強制制約」がない場合は変更できません.このコードでは
変更はありませんが、特に「バイトコード強化」テクノロジーの前では、コードが実行されると何でも起こります.
切り込みが発生すると、変化する可能性があります.だからコンパイラはこのような最適化をしないので、この時は「+」運を行います.
計算時に次のような結果にコンパイルされます.
StringBuilder temp = new StringBuilder();
temp.append(a).append("b");
String b = temp.toString();
注:このコンパイル結果とコンパイル時の統合の最適化は、太った兄が捏造したものではない.
コマンドを実行すると、これらの内容が実際に証明されます.
2番目の出力true.
1番目の出力falseとは対照的に,重畳変数cに対してfinal修飾子があることを区別した.
定義的にcを強制的に制約することは許されないが,finalは可変ではないため,コンパイラは自然に結果が
可変ではありません.
finalにはさらに多くの特性があり、5章で再び親密に接触します.
3番目の出力false.
そのオーバーラップ内容はメソッドに由来し、メソッド内に定数の参照が返されますが、コンパイラは
方法の内部で何をしたかを見てみましょう.このような最適化はコンパイラを困惑させるので、コンパイラは再帰的に知る必要があるかもしれません.
いったい何を返すのか、再帰の深さは予測不可能であり、再帰後も指定を必ず返すとは限らない.
の双曲線コサインを返します.また、定数が返されても、定数の参照に対してコピーが返されます.
コピーはfinalではありません.
 
3. このプログラムの結果は何ですか.
public static void test3() {
String a = "a";
String b = a + "b";
String c = "ab";
String d = new String(b);
println(b == c);
println(c == d);
println(c == d.intern());
println(b.intern() == d.intern());
}

 結果:
false
false
true
true
Intern()メソッドを呼び出すと、JVMはこの定数プールでequals()方を通過します.
メソッドは、等値のStringが存在するかどうかを検索し、存在する場合は、定数プール内のStringオブジェクトのアドレスを直接返します.若し
見つからない場合は、等値の文字列(すなわち、等値のchar[]配列文字列が作成されますが、char[]は新しく開発されたものです.
サブコピースペース)を使用して、この新しい作成スペースのアドレスを返します.同じ文字列であればintern()を呼び出す
メソッドの場合、定数プール内のStringに対応する参照が得られるため、2つの文字列はintern()操作で等号になります.
マッチします.
 
4.  String“+”
元のコードは次のとおりです.
String a = "a";
String b = "b";
String c = a + b + "f";

 
コンパイラは次のようにコンパイルします.
String a = "a";
String b = "b";
StringBuilder temp = new StringBuilder();
temp.append(a).append(b).append("f");
String c = temp.toString();

 
5. String、StringBufferとStringBuilderの違い
この3つのクラスの文字列処理における位置については言うまでもなく、彼らにはいったいどんなメリットとデメリットがあり、いったいいつ誰を使うべきなのか.以下の点から説明します
 
5.1.実行速度の比較:StringBuilder> StringBuffer  >  String
 
5.2.String<(StringBuffer,StringBuilder)の理由
 
String:文字列定数
 
StringBuffer:文字作成変数
 
StringBuilder:文字作成変数
 
上の名前から分かるように、Stringは「文字の定数」、つまり変えられないオブジェクトです.この言葉の理解に疑問を抱くかもしれません ,たとえば、このコード:
 String s = "abcd";
 s = s+1;
 System.out.print(s);// result : abcd1

 
 私たちはString型の変数sを変えたのに、どうして変わっていないと言ったのですか.実はこれは1種の欺瞞で、JVMはこのようにこのコードを解析したのです:まずオブジェクトsを作成して、abcdを与えて、それから新しいオブジェクトsを作成して第2行のコードを実行して、つまり私達の前のオブジェクトsは変化していないので、Stringタイプは変えることができないオブジェクトだと言って、このようなメカニズムのため、Stringで文字列を操作するたびに、実際には新しいオブジェクトがどんどん作成されていますが、元のオブジェクトがゴミになってGCで回収されてしまうので、実行効率がどれほど低いかがわかります.
 
     StringBufferはStringBuilderとは異なり、文字列変数であり、変更可能なオブジェクトです.文字列を操作するたびに、実際にはオブジェクト上で操作されます.これにより、Stringのように外部のオブジェクトを作成して操作することはありません.もちろん、速度が速くなります.
 
5.3.特殊な例:
String str = “This is only a” + “ simple” + “ test”;
StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

 
strオブジェクトを生成する速度が速すぎることに驚くでしょうが、このときStringBufferは速度的に全然優位を占めていません.実はこれはJVMのトリックで、実際には:
 
    String str = “This is only a” + “simple” + “test”;
 
実は、
 
    String str = “This is only a simple test”;
 
だからあまり時間はかかりません.しかし、ここで注意しなければならないのは、文字列が別のStringオブジェクトから来ている場合、速度はそれほど速くありません.例えば、
 
    String str2 = “This is only a”;
 
    String str3 = “simple”;
 
    String str4 = “test”;
 
    String str1 = str2 +str3 + str4;
 
このときJVMはきちんと元のやり方で行います.
 
5.4.StringBuilderとStringBuffer
 
StringBuilder:スレッドが安全でない
 
StringBuffer:スレッドが安全
 
文字列バッファで複数のスレッドに使用される場合、JVMはStringBuilderの動作が安全であることを保証することはできません.彼の速度は最も速いですが、StringBufferが正しく動作することを保証することができます.もちろん、ほとんどの場合、私たちは単一スレッドで行う操作なので、多くの場合、StringBufferではなくStringBuilderを使用することをお勧めします.それが速度の原因です.
 
 
 
           3つの使用に関するまとめ:1.少量のデータを操作する場合=String
 
                        2.単一スレッド操作文字列バッファで大量のデータを操作=StringBuilder
 
                        3.マルチスレッド操作文字列バッファで大量のデータを操作=StringBuffer