Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
上記のサンプルコードのステートメントの結果として作成されるオブジェクトの数とその理由は?作成されたオブジェクトの数を確認できるIDE)はありますか(デバッグモードで)。
驚くべきことに、答えはゼロです。
-128〜+127のすべてのInteger
sは、JVMによって事前に計算されます。
コードは、これらの既存オブジェクトに対するreferencesを作成します。
厳密に正しい答えは、作成されるInteger
オブジェクトの数はindeterminateです。 0〜3、または2561 またはそれ以上2、 応じて
int
値のボックス化に依存する他のコードがその前に実行されるかどうか4。-128〜127のInteger
値は、precomputedである必要はありません。実際、ボクシング変換を指定した JLS 5.1.7 は次のように述べています。
ボックス化される値pが-128〜127(3.10.1)を含むint型の整数リテラルである場合、aとbを2つのボックス化変換の結果とします。常にa == bです。
注意すべき2つのこと:
Integer.valueof(int)
のjavadocでさえ、結果が熱心にキャッシュされることをspecifyしません。
Java Java.lang.Integer
のSEソースコードをJava 6から8まで調べた場合、現在のJava SE実装戦略は値を事前に計算することですが、さまざまな理由(上記を参照)で、「オブジェクトの数」の質問に明確な答えを出すにはまだ十分ではありません。
1-上記のコードの実行がJavaのバージョンでInteger
のクラス初期化をトリガーすると、クラス初期化中にキャッシュが積極的に初期化されます。
2-キャッシュがJVM仕様に必要なサイズよりも大きい場合、さらに大きくなる可能性があります。 Javaの一部のバージョンでは、JVMオプションを使用してキャッシュサイズを増やすことができます。
3-ボクシングを実装するためのプラットフォームの一般的なアプローチに加えて、コンパイラーは、コンパイル時に計算の一部またはすべてを実行できるか、完全に最適化することができることを発見できます。
4-このようなコードは、整数キャッシュの遅延初期化または熱心な初期化をトリガーできます。
まず第一に:他の人が既に述べたように、あなたが探している答えは_0
_です。
しかし、もう少し詳しく見ていきましょう。スティーブンがメンチオニングしたように、それはあなたがそれを実行する時間に依存します。キャッシュは実際には遅延初期化されるためです。
Java.lang.Integer.IntegerCacheのドキュメントを見ると:
キャッシュは最初の使用時に初期化されます。
これは、実際に作成した整数を呼び出すのが初めての場合:
2回目にそれらを呼び出すと、0個のオブジェクトが作成されます。
数字を少し大きくすると、事態はさらに面白くなります。例えば。次の例で:
_Integer i = 1500;
_
有効なオプションは次のとおりです:0、1、または1629から2147483776までの任意の数値(今回は作成された整数値のみをカウントします。なぜですか?整数キャッシュ定義の次の文に答えがあります。
キャッシュのサイズは-XX:AutoBoxCacheMax =オプションで制御できます。
したがって、実際に実装されるキャッシュのサイズを変えることができます。
つまり、上記の行に到達できます。
覚えておいてください:これはOracle/Open JDKでのみ保証されます(バージョン7および8をチェックしました)
ご覧のとおり、完全に正しい答えを得るのはそれほど簡単ではありません。しかし、_0
_と言うだけで人々は幸せになります。
PS:menthonedパラメーターを使用すると、次のステートメントを真にすることができます:Integer.valueOf(1500) == 1500
コンパイラーはInteger
オブジェクトをint
sにアンボックスし、それらに対して intValue()
を呼び出して演算を行い、 Integer.valueOf
を呼び出します は、int
変数に割り当てられたときにInteger
の結果をボックス化するため、例は次と同等です。
Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());
割り当てj = i;
は、新しいオブジェクトを作成しない、完全に通常のオブジェクト参照割り当てです。ボックス化もボックス化解除も行わず、Integer
オブジェクトが不変である必要はありません。
valueOf
メソッドは、オブジェクトをキャッシュし、特定の番号に対して毎回同じインスタンスを返すことができます。 int -128〜+127をキャッシュすることはrequiredです。 i = 3
の開始番号については、すべての番号が小さく、キャッシュされることが保証されているため、作成する必要があるオブジェクトの数はです。厳密に言えば、valueOf
はインスタンスをすべて事前に生成するのではなく、遅延してキャッシュすることが許可されているため、この例では最初にオブジェクトを作成する可能性がありますが、プログラム中にコードが繰り返し実行されると、作成されるオブジェクトの数毎回平均が0に近づく。
インスタンスがキャッシュされないより大きな数(i = 300
など)で開始するとどうなりますか?その後、各valueOf
呼び出しは1つの新しいInteger
オブジェクトを作成する必要があり、そのたびに作成されるオブジェクトの総数は3です。 。
(または、多分それはまだゼロ、あるいは多分数百万です。コンパイラや仮想マシンは、その動作がそうでない限り、パフォーマンスや実装の理由でコードを書き換えることができます。変更されたので、結果を使用しない場合、上記のコードを完全に削除できます。または、j
を印刷しようとすると、j
は、上記のスニペットの後に常に同じ定数値になるため、コンパイル時にすべての算術を行い、定数値を出力します。コードを実行するために舞台裏で行われる実際の作業量は常に実装の詳細。)
Integer.valueOf(int i)メソッドをデバッグして、自分で調べることができます。このメソッドは、コンパイラによるオートボクシングプロセスによって呼び出されます。