[セットトップ]JavaのStringの詳細(繰り返し研究)


JAVAにおけるequalsと==の違い
 
==2つのオブジェクトのアドレスを比較し,equalsは2つのオブジェクトの内容を比較する.equalsがtrueの場合,==がtrueとは限らないことは明らかである.
 
しばらく振り回されてまた本を調べて、ついにStringという特殊な相手に少し悟った.
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = "Monday";
    }
}
何か問題がありますか.
1.Stringからの懸念
上のプログラムには、いったい何人のオブジェクトがありますか?
多くの人が口にしたかもしれません:2つ、s 1とs 2
どうして?
Stringはfinalクラスで、その値は可変ではありません.
理にかなっているように見えるので、チェックしてみましょう.少しプログラムを変更してください.
結果が表示されます.
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = "Monday";
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
    }
}
プログラムをコンパイルして実行し、出力:s 1==s 2
どうしてs 1==s 2なの?
==明らかに、s 1とs 2は同じStringオブジェクト--「Monday」を参照している!
2.千変万化のString
もう少しプログラムを変更すると、もっと奇妙な発見があります.
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = new String("Monday");
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
s 2をnewオペレータで作成します
プログラム出力:
s1 != s2
s1 equals s2
うん、明らかに?
s 1 s 2はそれぞれ2つの「Monday」Stringオブジェクトを参照している
しかし、なぜ2つのプログラムが違うのでしょうか.
3.Stringのプールで泳ぐ
ははは、本をめくってやっと答えを見つけた.
元は、プログラムが実行されると文字列バッファが作成されます.
s 2="Monday"のような表現を使って文字列を作成する場合、JAVAはまず
このStringバッファで同じ値のオブジェクトを探し、最初のプログラムではs 1が先に
プールに入れたので、s 2が作成されると、プログラムは同じ値のs 1を見つけました.
s 2をs 1が参照するオブジェクト「Monday」を参照
2段目のプログラムでは、newオペレータを使用して、彼はプログラムに理解しています.
「新しいものが欲しい!古いものは要らない!」と新しい「Monday」Stingオブジェクトが作成されました
メモリに建てられています.彼らの値は同じですが、位置が異なり、プールで泳いでいます.
一人は岸辺で休んでいます.あら、資源の浪費ですね.同じなのに何を分けなければなりませんか.
4.ダイビングを続ける
プログラムの再変更:
public class TestString {
    public static void main(String[] args) {
        String s1 = "Monday";
        String s2 = new String("Monday");
        s2 = s2.intern();
        if (s1 == s2)
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s2");
        if (s1.equals(s2))
            System.out.println("s1 equals s2");
        else
            System.out.println("s1 not equals s2");
    }
}
今回加入:s 2=s 2.intern();
わあ!プログラム出力:
s1 == s2
s1 equals s2
もとは、プログラムはs 2を新しく作った後に、またintern()で彼を池の中でひっくり返しました
ははは、今回s 2とs 1は同じ対象を引用しました
メモリの消費量を削減
5.==equals()との争い
Stringはオブジェクトです.2つの異なるStringオブジェクトの値が同じかどうかを比較します.
明らかにequals()という方法を用いる
しかし、プログラムにそんなに多くのStringオブジェクトがあれば、equalsを何度も使います.
より良い方法:
すべてのStringをintern()バッファに行きましょう
newを使うときにこの操作をしたほうがいいです.
String s2 = new String("Monday").intern();
Stringオブジェクトの値を=で比較できるようになりました
爽やかですね.速くて便利です.
 
テストコード:
public class StringAddress {
 public static void main(String[] args) {  String a = "hehe";  String b = "hehe";  String c = new String("hehe");  String d = a;  String e = c.intern();  if (a == b)   System.out.println(「a==b---a='hehehe'を使用して文字列を作成する場合、JAVAはまずStringバッファで同じ値を探しますが、見つかったら新しいオブジェクトを作成しません」).  if (a == c)   System.out.println(「a==c---newオペレータを使用してメモリを再申請」);  if (a.equals(c))   System.out.println(「a.equals(c)---値が同じで、メモリアドレスが異なる」);  if (a == d)   System.out.println("a==d---a==d ==> a.equals(d)");  if (a.equals(d))   System.out.println("a.equals(d)");  if (a == e)   System.out.println(「a==e---intern()後はStringプール」);  System.out.println(System.getProperty("user.dir")); }}
-------------------------------------------------------------------------------------------- 
 
StringとStringBufferの違い
特定の場合、Stringオブジェクトの文字列結合は、JVMによってStringBufferオブジェクトの結合として解釈されるため、Stringオブジェクトの速度はStringBufferオブジェクトよりも遅くはありません.特に、以下の文字列オブジェクト生成では、String効率はStringBufferよりもはるかに速いです.String S 1=「This is only a」+「simple」+"test";StringBuffer Sb=new StringBuilder("This only a").append("simple").append("test");String S 1オブジェクトを生成する速度が速すぎて、この時StringBufferは意外にも速度的に全然優勢ではありません.実はこれはJVMのトリックで、JVMの目には、このString S 1="This is only a"+"simple"+"test";実はString S 1="This is only a simple test";だからもちろんあまり時間はかかりません.しかし、ここで注意しなければならないのは、文字列が別のStringオブジェクトから来ている場合、速度はそれほど速くありません.例えば、String S 2="This is is only a";String S 3="simple";String S 4="test";String S 1=S 2+S 3+S 4;このときJVMはきちんとしたやり方で
//String+String  String tempstr = "abcdefghijklmnopqrstuvwxyz";  int times = 3500;  long lstart1 = System.currentTimeMillis();  String str = "";  for (int i = 0; i < times; i++) {   str += tempstr;  }  long lend1 = System.currentTimeMillis();  long time1 = (lend1 - lstart1)/1000;  System.out.println(「String+String時間:」+time 1+「ミリ秒」);    //"abcdefghijklmnopqrstuvwxyz"+"abcdefghijklmnopqrstuvwxyz"  long lstart2 = System.currentTimeMillis();  for (int i = 0; i < times; i++) {   str = "abcdefghijklmnopqrstuvwxyz"+"abcdefghijklmnopqrstuvwxyz";  }  long lend2 = System.currentTimeMillis();  long time2 = (lend2 - lstart2)/1000;  System.out.println("a b cdefghijklmnopqrstuvwxyz+a b cdefghijklmnopqrstuvwxyz時間:"+time 2+"ミリ秒");
  //StringBuffer.append()  long lstart3 = System.currentTimeMillis();  StringBuffer sb = new StringBuffer();  for (int i = 0; i < times; i++) {   sb.append(tempstr);  }  long lend3 = System.currentTimeMillis();  long time3 = (lend3 - lstart3)/1000;  System.out.println(「StringBuffer.append()時間:」+time 3+「ミリ秒」);
 
 
---------------------------------------------------------------------------------------------
いくつかのオブジェクトが作成されました
String   s   =   new   String(「xyz」).この文はいくつのオブジェクトを作成しますか?1つかもしれません.定数プールにはすでに「xyz」というオブジェクトが存在する可能性があるため、この文は定数プールに作成されず、スタックに1つのオブジェクトのみが作成されます.定数プールに「xyz」が存在しない場合、2つが作成されます.
 
String s="a"+"b";いくつかのオブジェクトを作成
次に、私の推測を簡単に証明し、まずこのクラスをコンパイルします.
 
public class Test { 
private String s = "ab"; 
}

classファイルの代替をコピーし、次のように変更します.
 
public class Test { 
private String s = "a" + "b"; 
}

再コンパイルし、ueなどのテキストエディタで開き、バイナリの内容を見ると、2つのclassファイルが完全に一致し、1バイトも悪くないことがわかります.
OK,真相が明らかになった.実行期間の処理String b=「a」+「b」はまったく存在しない.このようなコードの問題は,コンパイル時に直接最適化された.
 
Stringプールには、「」および+を使用して作成されたStringオブジェクトのみが追加され、newまたはString変数+「」を使用する他の状況は、オブジェクトを格納するスタックにあります.
スタック(Stack):レジスタに次ぐ速度で基本タイプ(byte,int,char)とオブジェクト参照を保存します.
ヒープ(heap):複雑なオブジェクトを格納します.Stringにはchar[]型配列で格納されたValue属性があります.