特殊なString型でJavaを[ターン]

文字列内のJavaは、次の2つの形式で作成された特別なラッパークラスのデータです。

  1. 文字列s = "ABC";
  2. 文字列s =新しいString( "ABC");

第一のスタックにおける参照変数s Stringオブジェクトクラスを作成し、次いで3チャースタック値を作成しない場合は、「ABC」は、文字列定数プールに格納されているかどうかを調べるために ' 、その後、「B」、「C」、およびその値からなるスタックで作成されたchar型の3つの値のちょうど配列であるヒープオブジェクトにStringオブジェクトを作成{「A」、「B」、「C」} 「ABC」の文字列定数プールに格納されている場合、文字列定数プールへ、オブジェクトが格納されている文字列オブジェクトは、オブジェクトの最後のアドレスにS-ポイントは、文字列定数プール内の「ABC」の値を見つけます。ターゲットオブジェクト、オブジェクトの点sの、アドレス。

最初の機能:JVMは自動的に新しいオブジェクトを作成する必要があるかどうかを判断するためにスタックデータの実際の状況に応じました。

図2に示すように、文字列S =新しい文字列(オブジェクト);「ABC」に起因する第2のステップは作成されているが、第一の実施形態への参照を作成する最初のステップと第二文字列オブジェクトが=「ABC」、二つのステップ1に分解することができますJVMのヒープが唯一の新しい文字列オブジェクトを作成しますので、文字列定数プールを保存し、その株式価値スタックの3種類のchar値があります。

第二の特徴:いないとにかかわらず、その文字列値の新しいオブジェクトを作成する必要があるかどうか、同じである、ヒープ内の新しいオブジェクトを作成します。

文字列の比較の話をする前に、我々は==とequalsの違いを理解しておく必要があります
ので、等しく、==は同じであり、達成するために等しい==すべてのJavaクラスは、基本クラスObjectから継承するため、使用中のオブジェクト、多くでありますJava APIのクラスは、パッケージの種類、文字列のような基本的なデータ型を備え、equalsメソッドのほとんどをオーバーライドするターゲットアドレス、。クラスの==アドレス文字列は、2つのオブジェクトを比較するために使用される、コンテンツ(値)に等しい2つの文字列オブジェクトを比較します。

文字列定数プールを使用します

String s0 = "abc"; 
String s1 = "abc"; 
System.out.println(s0==s1); //true  可以看出s0和s1是指向同一个对象的。

文字列==との違いに等しいです

String s0 =new String ("abc"); 
String s1 =new String ("abc"); 
System.out.println(s0==s1); //false 可以看出用new的方式是生成不同的对象 
System.out.println(s0.equals(s1)); //true 可以看出equals比较的是两个String对象的内容(值)

OKをコンパイルします

String s0="helloworld"; 
String s1="helloworld"; 
String s2="hello" + "word"; 
System.out.println( s0==s1 ); //true 可以看出s0跟s1是同一个对象 
System.out.println( s0==s2 ); //true 可以看出s0跟s2是同一个对象

分析:「HelloWorldの」におけるS0とS1の例では、文字列定数であり、それらはコンパイル時に決定されているので、それはS1にS0よう==真;および「こんにちは」と「世界」も文字列でありますS2は定数プール「のHelloWorld」となるように文字列定数の複数の互いに接続された文字列、文字列定数と確かに独自ので、またS2のコンパイルでは、文字列定数に解析されるとき、定数参照。だから我々は、S0 == S1 == S2になってきました。

コンパイル時間を決定することはできません

String s0="helloworld"; 
String s1=new String("helloworld"); 
String s2="hello" + new String("world"); 
System.out.println( s0==s1 ); //false  
System.out.println( s0==s2 ); //false 
System.out.println( s1==s2 ); //false

分析:新しいString()文字列を使用して作成したが、自身のアドレス空間を持つ定数プールに入れないで作成する)(それはコンパイル時に決定することができない、一定ではないので、新しい文字列文字列。
S0は定数プール「のhelloworld」の参照、彼らはコンパイル時に判断できないため、S1であるので、「HelloWorldの」実行時に作成される新しいオブジェクトへの参照、ため、新しい文字列の後半部分のS2(「世界」)であるので、それはできませんOKコンパイル、それはまたの新しく作成されたオブジェクト「のhelloworld」への参照です。

コンパイラの最適化

String s0 = "a1"; 
String s1 = "a" + 1; 
System.out.println((s0 == s1)); //result = true  
String s2 = "atrue"; 
String s3= "a" + "true"; 
System.out.println((s2 == s3)); //result = true  
String s4 = "a3.4"; 
String s5 = "a" + 3.4; 
System.out.println((a == b)); //result = true

分析:プログラムをコンパイルし、JVM意志定数文字列「+」クラスがA1にすでにある後「」+ 1、コンパイラの最適化を取るために、接続後の値を最適化するために接続されています。コンパイル時間の値が最終結果に該当する文字列定数として確立ので、上記の手順であります

コンパイル時間を決定することはできません

String s0 = "ab"; 
String s1 = "b"; 
String s2 = "a" + s1; 
System.out.println((s0 == s2)); //result = false

分析:文字列参照のJVM、接続されている「+」ので、文字列の文字列の参照が存在し、プログラムの値を参照することによりコンパイルされるが、決定することができない、すなわち、「」+ s1はコンパイラを最適化することができません、唯一の動的な接続後に新しいアドレスの割り当てとプログラムの実行中にS2を割り当てます。したがって、上記の手順はfalseになります

OKをコンパイルします

String s0 = "ab"; 
final String s1 = "b"; 
String s2 = "a" + s1;  
System.out.println((s0 == s2)); //result = true

分析:および[6]の唯一の違いは、それらの定数プールへのコンパイル時定数の値にローカルメモリのコピーとして解釈又はそのまで埋め込まれる変数の最終的な変更のために、ストリングS1の最終変形の付加でありますバイトコードストリーム。したがって、この場合には「」+ S1及び「the」+「B」効果は同じです。したがって、上記の手順の結果は真です。

時間をコンパイルすることに決定することはできません。

String s0 = "ab"; 
final String s1 = getS1(); 
String s2 = "a" + s1; 
System.out.println((s0 == s2)); //result = false 
private static String getS1() {  return "b";   }

分析:列基準S1用のJVMは、その値がコンパイル時にのみ、プログラムを実行するメソッドを呼び出した後に決定することができず、この方法は、値「」動的に接続及びS2にアドレスを割り当てるを返すように上記の手順の結果それは偽です。

文字列の不変のデザインについて:

文字列は不変クラス(注:プリミティブラッパークラスは不変である)であり、典型的な代表も不変の典型的なアプリケーションの設計パターン、変数、文字列を一度に変更初期化することができない後に、オブジェクトの状態への変更を禁止し、それによって共有オブジェクトを増大させます堅牢性は、エラーがアクセスオブジェクト削減するだけでなく、複数のスレッドが共有する場合に同期化する必要がなくなります。
不変モードは以下の2点を中心に達成するために:

  1. コンストラクターに加えて、他の機能(少なくとも任意のパブリック関数)任意のメンバ変数を変更してはなりません。
  2. 任意のメンバ変数は変更されていない元のオブジェクトを維持しながら、新たな値が、新しいオブジェクトに格納されなければならない機能の新しい値を取得します。

文字列の不変性は、プラス記号を使用して文字列変数コストにつながりました。

String s = “a” + "b” + "c”; 
String s1  =  "a"; 
String s2  =  "b"; 
String s3  =  "c"; 
String s4  =   s1  +  s2  +  s3;

分析:文字列S =「ABC」に相当する変数sを作成するステップと、上記の例は、コンパイラによって見ることができるが最適化されており、ここでの唯一のオブジェクトを作成します。上記の例では、我々は、オブジェクト作成に相当する、S4がコンパイル時に最適化することができません知ることができます。

StringBuffer temp = new StringBuffer();
temp.append(s1).append(s2).append(s3);
String s = temp.toString();

上記解析結果により、文字列オペレータに参加することができることを推測することは容易である(+)分析は非効率的に、このコードのような形。

public class Test { 
    public static void main(String args[]) { 
        String s = null; 
            for(int i = 0; i < 100; i++) { 
                s += "a"; 
            } 
    } 
}

それぞれ、+はStringBufferオブジェクトを生成し、その後、スロー後に追加します。次のサイクルに到達する前にStringBufferオブジェクトを再生し、その後最後までように文字列を追加し、そして。我々が追加する使用StringBufferオブジェクトを指示した場合、我々はNを保存することができます - 1回を作成し、時間のオブジェクトを破壊します。したがって、文字列を適用するためのサイクルの動作を追加する通常のStringBufferまたはオブジェクトと、接続するStringBulider

おすすめ

転載: www.cnblogs.com/zouwangblog/p/11141183.html