文字列の文字列連結の原則

文字列は非常に人気のクラスですのでJDK7 JVMがヒープに定数プール、プールJDK一定の移行に文字列定数に多くの方法を維持する前に、最適化されたJVM

メソッド領域は定数、スレッドが情報を入力するために使用される共有メモリ領域であり、領域JVMランタイムメモリ管理であり、一定の静的ストレージが仮想マシンをロードされています。

文字列を作成するには引用符を使用します

  • (単独注)道の文字列を作成するには引用符を使用だけで、文字列が一定である、それは一定のプールに保存されているコンパイル時に決定されています。
  • 引用符の文字列を作成し、最初のものはない定数オブジェクトは、定数プール内に作成されている場合、この定数オブジェクトへの等しいを見つけないように一定のプールを持っているだろう。任意の直接的なリターンのオブジェクトには、この一定の基準を。

したがって、この例を見て:

String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);//true

文字列を作成するための新しい方法

String a = new String("abc");

新しいキーワード、ヒープ上に割り当てられたメモリ内に疑いは、Stringクラスのオブジェクトを作成します。このように、スタック内のこの点への参照は、文字列オブジェクトのスタックです。

「ABC」は一定であるためすると、その定数プールは見つけることになりますスペースを割り当てていない場合は、そのような定数の存在は、存在しない、Stringオブジェクトヒープに一定のオブジェクトに対処するために、「ABC」の定数とスペースを入れます内部;定数pool'veは、この定数を得た場合、一定のオブジェクトは、あなたが直接聖歌定数プール参照を使用することを、あなただけのStringオブジェクトヒープを作成する必要があります。

新しいコンストラクタ入ってくる文字列定数は、ヒープは、Stringオブジェクトを作成しますが、オブジェクトは、コンテンツ(値)を格納するための新しい文字配列に行くことなく、直接、文字の文字列定数のオブジェクト配列(値)を使用しますアプリケーション、

詳細なリファレンス

/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param  original
*         A {@code String}
*/
public String(String original) {
   this.value = original.value;  //只是把传入对象的value和引用传给新的对象, 两个对象其实是共用同一个数组
   this.hash = original.hash;
}

構成プロセスはoriginal.valueによってプライベート修飾子ものの値、しかし、まだ2つのオブジェクトが同じクラスのオブジェクトであるため、直接他のオブジェクトの値を取得することができます。

IMG

だから、次の結果を持っています

public static void main(String[] args) {
      String s1 = new String("hello");
      String s2 = "hello";
      String s3 = new String("hello");
      System.out.println(s1 == s2);// false
      System.out.println(s1.equals(s2));// true
      System.out.println(s1 == s3);//false
  }

「+」演算子オン

一定の直和:

String s1 = "hello" + "word";
String s2 = "helloword";
System.out,println(s1 == s2);//true

ここでの真のは、S1のコンパイラの最適化を入れているため、直接文字列S1 =「helloword」になったということです。それはバックに等しく、

非常に直接的合計額

 public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = new String("b");
        String s4 = s1 + s3;
        String s5="ab";
        String s6 = s1 + s2;
            String s66= s1 + s2;
        String s7 = "a" + s2;
        String s8 = s1 + "b";
        String s9 = "a" + "b";

        System.out.println(s2 == s3);  //false   
        System.out.println(s4 == s5);   //false   s4 是使用了StringBulider来相加了
        System.out.println(s4 == s6);  //false  s4和s6 两个都是使用了StringBulider来相加了
        System.out.println(s6 == s66);     //false   两个都是使用了StringBulider来相加了
          System.out.println(s5 == s7);    //false   s7是使用了StringBulider来相加了
        System.out.println(s5 == s8);  //false   s8是使用了StringBulider来相加了
        System.out.println(s7 == s8);  //false  两个都是使用了StringBulider来相加了
        System.out.println(s9 == s8);  //false  两个都是使用了StringBulider来相加了
    }

以下は、次のとおりです。

  二つ以上の文字列定数の直接加え、「+」は、2つ以上の自動合成文字列定数文字列定数に対応し、事前コンパイル時に最適化されます。

、最適化されたバイトコードをコンパイルし、プラスに直接置くの定数を定義し、直接削除コンパイルします

 それ以外の場合は文字列がStringBuilderのに添加して使用されます。

文字列のインターン()メソッド。

これは、メソッドのネイティブである本はその機能を説明する文字列プールを表すStringオブジェクトが返され、文字列定数プールは既にこのStringオブジェクトのような文字列が含まれている場合は、そうでない場合は、この:定数プールに追加含まれており、Stringオブジェクトを返す文字列オブジェクト。

PermSizeをおよび-XX:起因永久割り当て世代で一定のプールに、JDK1.6の以前のバージョンで参照と、我々は-XXができる定数プールの容量によって制限されるMaxPermSizeのサイズ制限方法間接的エリア。

また、この方法では、書籍の例を見て、インターンへの参照を返し、JDK1.6とJDK1.7が同じ場所がありません。

public static void main(String[] args) {
    String str1 = new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern() == str1);

    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str2);
}

このコードJDK1.6では、2はfalseになります、JDK1.7で実行している、あなたは真と偽になります。

この本は、違いの理由は、こう述べています。ではJDK1.6、インターン()メソッドは、最初に文字列のインスタンスをコピーします恒久的な世代に遭遇し、文字列の引用の場合は、世代、しかしによって恒久的に返されますJavaヒープで作成されたStringBuilderの文字列のインスタンスが、それは、必ずしも同一の参照番号ではありませんfalseを返します。

インターンは、()のインスタンスを複製することはできませんJDK1.7は、定数プールのインスタンスを記録するだけ最初の発生、同じへの復帰を作る従ってインターン()文字列とStringBuilderのインスタンス引用文献。リターンfalseにSTR2比較は()が登場しましたStringBuilder.toStringを実行する前の「Java」文字列は、文字列定数プールには、「コンピュータを「初登場」の原則に準拠していない、その参照を持っている、とするのでソフトウェアは、「これは、文字列が最初に現れるので、trueを返します。

なぜなら、定数プールの違いJDK6 7,7がヒープに移動され、処理のための定数プールに違いがある、一定のプールにスタックのコピーを複製する文字列6、

定数プール、第1 str1.intern()に7つのだけ文字列オブジェクトのヒープ参照ヒープへのポインタを返すように偽の最初に出現することを、オブジェクトへの参照だけです。

第二偽7は、それが既に持っているので、「Javaは」偽ので、定数プール、()プール内のオブジェクトに一定の基準点を返すようstr2.intern、STR2、ヒープ・オブジェクトの参照ポイントであるオブジェクトであります

小さなSTRINGTABLEの説明

ただ、速度を上げるために、定数文字列定数プールは、定数を見つけるためにハッシュテーブル。簡単を維持します

文字列定数プール、設計時におけるJavaの定数プールは、また、これを張STRINGTABLEを従事する場合はここでは文字列定数プールに関する最初の言及は、実際には、あるマッチング速度を向上させるためには、すぐに見つけるために参照を対応する文字列を検索するために、アレイを介して対応するバケット、次いでループを見つけるためにハッシュコード列に応じて我々のハッシュテーブルのようなビット、。あなたは、文字列を見つけた場合は、参照を返すには、一定のプールに文字列定数を見つけ、そしてSTRINGTABLE内部への参照を保存しません。

JDK7,8で、-XXによって:StringTableSizeサイズますRESDLL.DLLパラメータ

インターンは、その前の()メソッドをJDK1.6

JDK6で、Javaヒープメモリのメモリ割り当ての永久的な生成、および永久世代の定数プールが、物理的に分離され、インターン方法の実装、文字列定数プール、仮想マシンは、文字列定数プールのコピーに存在しない場合、および参照を返し、文字列がすでに存在する場合、この定数は、そのオブジェクトの参照定数プールを返します。それも、PermGenメモリオーバーフローが発生し、パフォーマンスの低下をもたらし、過度の文字列定数プールを避けるために注意インターンの方法を使用する必要があります。

https://blog.csdn.net/soonfly/article/details/70147205から:(画像を理解するための写真を見て)

IMG

もちろん、この定数プールと原子炉は、物理的に分離されています。

とにかく、私たちは言葉の「コピー」をつかむ必要があり、それが一定のプールの内容に保たれている「ABC」の定数オブジェクト。

ポイントの例で詳細を見て:

   public static void main(String[] args) {
        String a = new String("haha");
        System.out.println(a.intern() == a);//false
    }

まず第一に、「笑」、出力が一定のプールではありません見、それは、一定のプールでLDC命令によって下をこの定数オブジェクトを残す、「笑」の文字列定数プールに追加され、その後、STRINGTABLEで定数を追加参照(このような参照は、文字列の文字列オブジェクトのアドレスである)、そして、それは異なっていなければならないので、ヒープの基準点は、文字列オブジェクトのアドレスです。(スタックにおいて、処理中の領域)。

jdk1.7インターン()メソッド

ある場合はJDK 1.7の後、インターン方法はまだ一定のプールがすでに存在しているがあるかどうかを問い合わせに行くだろう、それは違いはありません前にある参照定数プールを返し、定数プールに対応する文字場合の違いは、そのです文字列は、文字列は定数プールにコピーされないが、定数プールで発生元の文字列への参照のみ。簡単に言えば、変更物事を置くために、プールの通常の量である:オリジナルは、定数プールで見つけることができない、一定のプールにコピーを作成し、1.7の後に、ヒープ上のアドレスの定数プール参照コピーに吸い込まれます。

もちろん、この時は、定数プールは、ヒープに来たメソッド領域から削除されます。

マップを見てください:

(写真からhttps://blog.csdn.net/soonfly/article/details/70147205)

IMG

私たちの書籍の例にそうルックバック

public static void main(String[] args) {
    String str1 = new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern() == str1);

    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str2);

例を見てください:

String str2 = new String("str")+new String("01");
str2.intern();
String str1 = "str01";
System.out.println(str2==str1);//true

定数プールは、文字列のヒープオブジェクトへの参照を生成するので、trueを返します。このような理由から、あまりにも、文字列の唯一のヒープがオブジェクトSTR2、その後、コールインターンは、定数をプール「str01」定数オブジェクトは、ありません。

そして、それが引用されているので、時間にSTR1の割り当てを与え、その定数プールを探しに行く、一定のオブジェクトを見つけ、それはオブジェクトへの一定の基準を返し、STR2はアドレ​​スを参照Stringオブジェクトヒープで指されます。

だから、同じことにSTR1とstr2ポイント、それは本当です。

JDK7参照が定数プールにコピーされますが、定数プールの機能に影響を与えない、参照が最終的になるので、一定の増加性能定数プールが参照されているか、定数を小さくする役割を再生することができます作成​​定数プールを減らすことですが、実際のオブジェクトを指しています。

参考ブログ

https://www.cnblogs.com/wangshen31/p/10404353.html

おすすめ

転載: www.cnblogs.com/xiezc/p/11913830.html