46

整数用のJava定数プールがどのように機能するかを理解できません。

私は文字列の動作を理解しているので、整数定数の場合も同じであると自分自身を正当化することができます。

したがって、整数の場合

Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1==i2); // True

Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1==i2); // False

ここまで、すべてが私の頭の中にあります。

ダイジェストできないのは、整数を127から増やすと動作が異なることです。この動作は127以降に変わります。以下は、コードスニペットです。

Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1==i2); // False. WHY?????

誰かが私がこれを理解するのを手伝ってもらえますか?

4

4 に答える 4

47

いいえ、数値の定数プールは文字列の場合と同じようには機能しません。文字列の場合、コンパイル時定数のみがインターンされますが、整数型のラッパー型の場合、その値に適用できる場合は、すべてのボクシング操作で常にプールが使用されます。したがって、たとえば:

int x = 10;
int y = x + 1;
Integer z = y; // Not a compile-time constant!
Integer constant = 11;
System.out.println(z == constant); // true; reference comparison

JLSは、プールされた値の狭い範囲を保証しますが、実装では、必要に応じてより広い範囲を使用できます。

保証はされていませんが、私が調べたすべての実装はInteger.valueOfボクシング操作を実行するために使用されることに注意してください。そのため、言語の助けがなくても同じ効果を得ることができます。

Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
System.out.println(x == y); // true

JLSのセクション5.1.7から:

ボックス化されている値pがtrue、false、1バイト、または\u0000から\u007fの範囲のchar、または-128から127(両端を含む)のintまたはshortの数値の場合、r1とr2を次の結果とします。 pの任意の2つのボクシング変換。r1==r2の場合は常にそうです。

理想的には、与えられたプリミティブ値pをボックス化すると、常に同一の参照が生成されます。実際には、これは既存の実装手法を使用して実行できない場合があります。上記のルールは実用的な妥協案です。上記の最後の節では、特定の共通の値を常に区別できないオブジェクトにボックス化する必要があります。実装は、これらを遅延または熱心にキャッシュする場合があります。他の値の場合、この定式化では、プログラマー側のボックス化された値のIDに関する仮定は許可されません。これにより、これらの参照の一部またはすべてを共有できるようになります(必須ではありません)。

これにより、ほとんどの場合、特に小さなデバイスで過度のパフォーマンスペナルティを課すことなく、動作が望ましいものになります。メモリ制限の少ない実装では、たとえば、すべてのchar値とshort値、および-32Kから+32Kの範囲のint値とlong値をキャッシュできます。

于 2012-10-27T07:24:13.227 に答える
29

-128Javaはからまでの整数プールを維持します127

以下のように整数を宣言する

Integer i1 = 127;

結果は

Integer i1 = Integer.valueOf(127);

したがって、最初のケースで実際に起こっていることは

Integer i1 = 127;<---Integer.valueOf(127);
Integer i2 = 127;<---Integer.valueOf(127);<---Same reference as first

Integerforクラス valueOf メソッドのソースコードから

public static Integer valueOf(int i) {
    if(i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

したがって、値がtoの間-128にある場合は同じ参照を取得し127valueOfそれ以外の場合はnew Integer(i)

また、参照は同じであるため、演算子はこの範囲の間で==返される整数に対して機能します。valueOf

于 2012-10-27T07:22:47.023 に答える
9

Javaは、範囲内の整数オブジェクトをキャッシュします-128 to 127。したがって、この範囲の値をwrapperオブジェクトに割り当てようとすると、boxing操作によってInteger.valueOfメソッドが呼び出され、次に、プールにすでに存在するオブジェクトへの参照が割り当てられます。

一方、この範囲外の値をwrapper参照型に割り当てると、その値Integer.valueOfの新しいIntegerオブジェクトが作成されます。したがって、この範囲外の値を持つオブジェクトのreferenceforを比較すると、次のIntegerようになります。false

それで、

Integer i = 127;  --> // Equivalent to `Integer.valueOf(127)`
Integer i2 = 127;

// Equivalent to `Integer.valueOf(128)`
// returns `new Integer(128)` for value outside the `Range - [-128, 127]`
Integer i3 = 128; 
Integer i4 = 128;

System.out.println(i == i2); // true, reference pointing to same literal
System.out.println(i3 == i4); // false, reference pointing to different objects

ただし、new演​​算子を使用して整数インスタンスを作成すると、ヒープ上に新しいオブジェクトが作成されます。それで、

Integer i = new Integer(127);
Integer i2 = new Integer(127);

System.out.println(i == i2); // false
于 2012-10-27T07:23:38.350 に答える
2

要するに、Javaキャッシュの新しいバージョンでは、整数は-128から127の範囲(256の値)です。ここを見て

整数と==の比較は正確に何をしますか?

于 2012-10-27T07:25:15.223 に答える