Java文字列の詳細を転載

5742 ワード

一、Javaにおけるデータ型の一つは基本型(primitive types)であり、int、short、long、byte、float、double、boolean、char(stringの基本型はないことに注意)の8種類がある.
このタイプの定義は、int a=3のようなものである.long b = 255L;と呼びます.なお、自動変数は、クラスのインスタンスではなく、クラスの参照ではなく、ここではクラスの存在はありません.例えばint a=3;ここのaは直接3という字の値を指している.これらの額面値のデータは,大きさが知ることができ,生存期間が知ることができ(これらの額面値はあるブロックに固定定義され,ブロックが終了するとフィールド値が消失する),速度を追求するためスタックに存在する.
もう1つは、Integer、String、Doubleなど、対応する基本データ型をパッケージするクラスデータです.これらのクラスデータはすべてスタックに存在し、Javaはnew()文でコンパイラに実行時に必要に応じて動的に作成されるため柔軟であるが、より多くの時間を費やすのが欠点である.
例えばJavaコード
public class Test {
public static void main(String[] args)
{
   int a1=1;         

   int b1=1;         

   int c1=2;         

   int d1=a1+b1;         

    Integer c = 3;           

   Integer d = 3;           

   Integer e = 321;           

   Integer f = 321;

   Long g = 3L;  

  System.out.println(a1==b1);   //true    1          

  System.out.println(c1==d1);   //true    2        

  System.out.println(c==d);   //true    3           

  System.out.println(e==f);   //false    4         

 }  

}
分析:
結果1:a 1=b 1は、上述したように、スタックに格納データを開く.
結果2:まず、スタックに変数c 1の参照を作成し、2の値を持つアドレスがあるかどうかを検索します.見つからない場合は、2という値を格納するアドレスを開き、c 1を2のアドレスに、d 1を2の値に加算しても2になります.スタックに2という値があるため、d 1を2のアドレスに直接指定します.これにより、c 1とd 1が同時に2のアドレスを指す場合がある.
次の結果を分析する前に、Javaの自動分解と梱包について終わりましょう.自動梱包時にintをIntegerにするときは、ルールがあります.intの値が-128-IntegerCacheです.high(127)では、新しいnewから出てきたIntegerオブジェクトではなく、スタックにキャッシュされたIntegerオブジェクトが返されます.(私たちはこのように理解することができて、システムはすでに-128から127の間のIntegerを1つのInteger配列の中にキャッシュして、もしあなたが1つのintを1つのIntegerオブジェクトになるならば、まずキャッシュの中で探して、見つけたら直接あなたに引用を返して、もう1つのnewを返す必要はありません)、もし-128-IntegerCache.high(127)でない時1つの新しいnewから出てきたIntegerオブジェクトを返します.
結果3:3は範囲内であるためキャッシュからデータを取得し、cとdは同じオブジェクトを指し、結果はtrueである.
結果4:321は範囲内ではないのでキャッシュからデータを取り出すのではなくnewオブジェクトが単独であり、eとfは同じオブジェクトを指しておらず、結果はfalseである.
二、Stringは特殊な包装類データである.一、StringはString str=new String(「abc」)を用いることができる.の形式で作成したり、String str="abc"を使用したりすることができます.に表示されます.
String str=「abc」オブジェクトを作成するプロセス
1まず、定数プールに「abc」という文字列オブジェクトが存在するかどうかを検索します.
2存在しない場合、定数プールに「abc」の文字列オブジェクトを作成し、strにオブジェクトを参照させる
3存在する場合strにオブジェクトを直接参照させる
注意:定数プールはクラス情報の一部であり、クラス情報がJVMメモリモデルに反映されるのは、JVMメモリモデルに存在するメソッド領域であり、すなわち、このクラス情報の定数プール概念はメソッド領域に存在する.一般に、この場合、「abc」はコンパイル時にバイトコードに書き込まれるため、classがロードされると、JVMは「abc」のために定数プールにメモリを割り当てるので、静的領域との差は多くない.
String str=new String(「abc」)インスタンスを作成するプロセス
1まずstrのStringタイプの参照を定義し、スタックに格納します.
2文字列定数プールで「abc」文字列オブジェクトが存在するかどうかを確認します.
3存在する場合はこのステップをスキップし、存在しない場合は文字列定数プールに「abc」という文字列オブジェクトを作成します.
4 new操作を実行し、スタックに指定されたオブジェクトabcを作成します.スタックのオブジェクトは文字列定数プールabcオブジェクトのコピーオブジェクトです.
5 strをスタック内の「abc」というオブジェクト(すなわち、このオブジェクトを格納するスタック内のアドレス)に向ける
二、詳細例:
public static void main(String[] args) {
    /**

     *    :    

     * JAVA   (JVM)            ,       String  ;

     *          ,        。

     *   String  final ,            。

     *      String   ,      intern()         。 

     */ 

    String s1 = "abc";    

    //↑              

    String s2 = "abc";    

    //↑              “abc”(  ),    0   ,         

    System.out.println("s1== s2 : "+(s1==s2));   

    //↑ true        , 

    System.out.println("s1.equals(s2): " + (s1.equals(s2)));   

    //↑ true      



    /**

     *    :  new String("")

     * 

     */ 

    String s3 = new String("abc"); 

    //↑        ,          ,       ; 

    //↑         s3      

    String s4 = new String("abc"); 

    //↑          “abc”  ,              

    System.out.println("s3== s4 : "+(s3==s4)); 

    //↑false   s3 s4         ,         ; 

    System.out.println("s3.equals(s4): "+(s3.equals(s4))); 

    //↑true  s3 s4     

    System.out.println("s1== s3 : "+(s1==s3)); 

    //↑false        ,      ,     

    System.out.println("s1.equals(s3): "+(s1.equals(s3))); 

    //↑true      



    /**

     *    : 

     *                 (  ) 。

     *    ,"ab" "cd"    ,    str1           。

     *              : String str1 = "abcd";

     */ 

    String str1 = "ab"+ "cd";  //1    

    String str2 = "abcd";  

    System.out.println("str1= str2 : "+ (str1 == str2)); 

    //↑             

    /**

     *    :

     *     str2   (     )   ,         ,    
  • 現在は、まずnew 1つのStringBuilder、それからappend(str 2)、append(「c」)である.そして
  • str 3は、toString()が返すオブジェクト*/
     String str1 = "abc";        
    
     String str2 = "ab";
    
     String str3 = str2+"c";
    
     System.out.println(str1==str3);  // false
    
    String str 1=「abc」を参照する.final String str2 = “ab”; String str3 = str2+”c”;
    System.out.println(str1==str3);  // true
    
    /**
  • シナリオ5:
  • intern()メソッドは、定数プール内の文字列のオブジェクトの参照
  • を返すことができる.
  • 最初は空の文字列プールで、クラスStringによってプライベートに維持されます.Internメソッド
  • が呼び出されると
  • の場合、プールにこのStringオブジェクトに等しい文字列がすでに含まれている場合(equals(Object)方
  • 法で決定)すると、プール内の文字列が返されます.そうでなければ、このStringオブジェクトをプールに追加し、
  • を返します.
  • このStringオブジェクトの参照.*/String str1 = “abc”; String str2 = newString(“abc”).intern(); System.out.println(str1==str2);//true

  • /**シナリオ6:
  • str 1の値を「bcd」に変更すると、JVMは定数プールに値が格納されていないアドレスを発見し、
  • は、このアドレスを開き、文字列の値がこのアドレスを指す新しいオブジェクトを作成します.
  • 実際にStringクラスは変更不可能なクラスとして設計されている.値を変更する場合は、

  • *できますが、JVMは実行時に新しい値に基づいてこっそり新しいオブジェクトを作成し、そのオブジェクトの
  • アドレスは、元のクラスへの参照を返します.この作成プロセスは完全に自動的に行われていますが、
  • です.
  • はより多くの時間を費やしました.時間要求に敏感な環境では、一定の不良影
  • が伴う.
  • が鳴ります.
  • */String str1 = “abc”; String str2 = “abc”; str1 = “bcd”; System.out.println(str1 + “,” + str2);//bcd, abc System.out.println(str1==str2);//false }