Javaの定数プールは通常、静的定数プールとランタイム定数プールの2つのタイプに分割されます
静的定数プール:クラスファイルの定数プール。クラスファイルの定数プールには、文字列(数)リテラル値、クラス、メソッド情報が含まれ、クラスファイルのほとんどのスペースを占有します。
ランタイム定数プール:JVMがクラスのロードを完了した後、クラスファイルの定数プールをメモリにロードし、メソッドエリアに保存します。私たちが通常話しているのは、メソッド領域のランタイム定数プールの一定のプールです。クラスファイルと比較した一定のプールのもう1つの重要な機能は、その動的性です。 Java言語は、コンピレーション期間中にのみ定数を生成する必要はありません。つまり、クラスファイルの定数プールの内容は、メソッドエリアランタイム定数プールに入ることができます。実行中、新しい定数もプールに配置できます。この機能は、開発者がより一般的に使用しています。文字列クラスのインターン()メソッド。
プログラムカウンター:プログラム実行のパイプラインであり、次に実行するコマンドを示します。
ローカルメソッドスタック:JVMがオペレーティングシステムメソッドを呼び出すために使用するスタック。
仮想マシンスタック:JVMがJavaコードを実行するために使用するスタック
仮想マシンヒープ:オブジェクトが保存され、Javaプログラムで新しくなったすべてのオブジェクトがヒープに保存されます。
メソッドエリア:定数、クラス情報、静的変数を保存します。これらは、クラスファイルがメモリに保存されている場所として理解できます。
一定のプーリングの利点:
一定のプールは、システムのパフォーマンスに影響を与えるオブジェクトの頻繁な作成と破壊を避けるために使用され、オブジェクトの共有を実現します。
たとえば、文字列定数プールを使用して、コンピレーション段階ですべての文字列リテラルを一定のプールに入れます。
1.メモリスペースを保存:一定のプールに同じリテラル値を持つすべての文字列定数がマージされ、1つのスペースのみを占有します
2。実行時間を保存:文字列比較を実行する場合、==はequals()よりも高速です。 2つの参照変数の場合、==を使用して参照が等しいかどうかを判断するため、実際の値が等しいかどうかを判断できます。
==基本的なデータ型とオブジェクト表現の意味は異なります。
基本データ型の場合:==比較はオブジェクトの基本データ型の値です:==比較はメモリ内のオブジェクトのメモリアドレスです
8つの基本的なデータ型クラッピングクラスと一定のプール
Javaの基本データ型のラッパークラスのほとんどは、定数プーリングテクノロジー、つまりバイト、ショート、整数、長い、文字、およびブール波を実装しています。
整数i1 = 40;整数i2 = 40; System.out.println(i1 == i2); // true
バイト、ショート、整数、長い、文字、これらの5つのラッパークラスは、デフォルトで対応するタイプの[-128、127]のキャッシュデータを作成し、定数プールに保存します。この範囲を超える場合、新しいオブジェクトが作成されます。
public static integer valueof(int i){assert integercache.high> = 127; if(i> = integercache.low && i <= integercache.high)return integercache.cache [i +(-integercache.low)];新しい整数(i)を返します。 }整数i1 = 400;整数i2 = 400; System.out.println(i1 == i2); // false
2. 2種類の浮動小数点数パッケージクラスが浮かんでおり、ダブルは定数プーリングテクノロジーを実装していません。
double d1 = 2.5; double d2 = 2.5; System.out.println(d1 == d2); // false
3。一定のプールを適用するためのシナリオ
(1).integeri1 = 40;整数は基本データ型intのラッパークラスであり、オブジェクトであるため、Javaはコンパイル時に自動ボクシング操作を実行し、コードをintegeri1 = integer.valueof(40)に直接カプセル化します。
(2).integeri1 = newinteger(40);この場合、新しいオブジェクトが作成されます
整数i1 = 40;整数i2 = new Integer(40); System.out.println(i1 == i2); // false
この場合、新しい整数は一定のプールで既存の定数を自動ボクシング参照することはありませんが、ヒープ内の新しいオブジェクトを直接生成します。
4。整数の詳細
整数i1 = 40;整数i2 = 40;整数i3 = 0;整数i4 = new Integer(40);整数i5 = new Integer(40);整数i6 = new Integer(0);整数i7 = 128;整数i8 = 128; System.out.println( "i1 = i2" +(i1 == i2)); System.out.println( "i1 = i2 + i3" +(i1 == i2 + i3)); System.out.println( "i1 = i4" +(i1 == i4)); System.out.println( "i4 = i5" +(i4 == i5)); System.out.println( "i4 = i5 + i6" +(i4 == i5 + i6)); System.out.println( "40 = i5 + i6" +(40 == i5 + i6)); System.out.println( "i7 = i8" +(i7 == i8));
i1 = i2 truei1 = i2+i3 truei1 = i4 falsei4 = i5 falsei4 = i5+i6 true40 = i5+i6 truei7 = i8 false
説明:ステートメントi4 == i5 + i6。 +演算子は整数オブジェクトに適用できないためです。まず、i5とi6は自動アンボクシング操作を実行し、値、つまりi4 == 40を追加します。整数オブジェクトを数値と直接比較することはできないため、i4は自動的にボックスを解除してint値40に変換します。最後に、このステートメントは数値比較のために40 == 40に変換されます。
文字列クラスと一定のプール
1.文字列オブジェクトを作成する方法
string s1 = "abdcd"; string s2 = new string( "abcd"); system.out.println(s1 == s2); // false
これら2つの異なる方法の作成方法には違いがあります。 1つ目は、定数プールにオブジェクトを取得することであり、2つ目はヒープメモリスペースに新しいオブジェクトを作成することです。
新しいオブジェクトを使用するだけで、ヒープに作成されます。
2.接続式+
(1)。 「+」接続によって生成された新しいオブジェクトのみが、「 "を含むテキストを使用して作成された文字列オブジェクト間の接続が文字列定数プールに追加されます。
(2)。 「+」を介して直接接続された2つのオブジェクト参照や、新しいモードで作成されたオブジェクトなどの他のフォームの場合、結果の新しいオブジェクトは文字列定数プールに追加されません。
string str1 = "str"; string str2 = "ing"; string str3 = "str" + "ing"; string str4 = str1 + str2; system.out.println(str3 == str4); // false string str5 = "string"; system.out.println(str3 == str5); // true
public static final string a = "ab"; //定数Apublic static final string b = "cd"; // constant bpublic static void main(string [] args){string s = a + b; // + concatenation string t = "abcd"でsを初期化します。 if(s == t){system.out.println( "s等しい、それらは同じオブジェクトです"); } else {system.out.println( "sはtに等しくなく、同じオブジェクトではありません"); }} sはtに等しく、それらは同じオブジェクトですAとBは両方とも定数であり、値は固定されているため、Sの値も固定されており、クラスがコンパイルされたときに決定されます。つまり、文字列s = a+b。相当:string s =” ab”+” cd”;
public static final string a; //定数Apublic Static Final String B; // constant bstatic {a = "ab"; b = "cd"; } public static void main(string [] args){// + concatenation string s = a + bでsを初期化します。文字列t = "abcd"; if(s == t){system.out.println( "s等しい、それらは同じオブジェクトです"); } else {system.out.println( "sはtに等しくなく、同じオブジェクトではありません"); }} sはtに等しくなく、同じオブジェクトではありませんAとBは定数として定義されていますが、どちらもすぐに割り当てられません。 sの値を計算する前に、それらが割り当てられたときとそれらが割り当てられる値は変数です。したがって、AとBが割り当てられる前に、それらのプロパティは変数に似ています。その後、Sはコンピレーション期間中に決定することはできませんが、実行時にのみ作成できます。
3.Strings1 = NewString( "xyz");いくつのオブジェクトが作成されましたか?
クラスの読み込みフェーズと実際の実行を検討してください。
(1)クラスの読み込みは、クラスで1回のみ実行されます。 「XYZ」は、クラスがロードされたときに作成され、居住します(クラスがロードされる前に「XYZ」文字列が居住している場合、居住用の「XYZ」インスタンスを繰り返し作成する必要はありません)。居住した文字列は、グローバルに共有された文字列定数プールに配置されます。
(2)このコードがその後実行されると、「XYZ」リテラルに対応する文字列インスタンスが固定されており、繰り返し作成されません。そのため、このコードは一定のプールのオブジェクトのコピーをコピーしてヒープに入れ、ヒープ内のオブジェクトへの参照をS1に渡して保持します。
このステートメントは2つのオブジェクトを作成します。
4.java.lang.string.intern()
クラスファイルの定数プールと比較したランタイム定数プールのもう1つの重要な機能は、その動的性です。 Java言語は、コンピレーション期間中にのみ定数を生成する必要はありません。つまり、クラスファイルの定数プールの内容はメソッド領域に入ることができます。ランタイム中に新しい定数をプールに配置することもできます。この機能は、開発者がより一般的に使用しています。文字列クラスのインターン()メソッド。
文字列のインターン()メソッドは、定数プールに等しい等しい列があるかどうかを調べます。ある場合、文字列への参照を返します。いいえがある場合は、一定のプールに独自の文字列を追加します。
public static void main(string [] args){string s1 = new String( "Computer");文字列s2 = s1.intern();文字列S3 = "コンピュータ"; System.out.println( "s1 == s2?" +(s1 == s2)); System.out.println( "s3 == s2?" +(s3 == s2));}s1 == s2? falses3 == s2?真実
要約します
上記は、Java Constant Poolsを詳細に探索することです。私はそれが誰にでも役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。