27

==128以降の整数値に対して整数演算子が機能しないのはなぜですか? 誰かがこの状況を説明できますか?

これは私の Java 環境です。

java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01, mixed mode)

サンプルコード:

Integer a;
Integer b;
a = 129;
b = 129;

for (int i = 0; i < 200; i++) {
    a = i;
    b = i;

    if (a != b) {
        System.out.println("Value:" + i + " - Different values");
    } else {
        System.out.println("Value:" + i + " - Same values");
    }
}

コンソール出力の一部:

Value:124 - Same values
Value:125 - Same values
Value:126 - Same values
Value:127 - Same values
Value:128 - Different values
Value:129 - Different values
Value:130 - Different values
Value:131 - Different values
Value:132 - Different values
4

7 に答える 7

25

Integer のソース コードを確認してください。そこに値のキャッシュが表示されます。

キャッシュは、 を使用する場合Integer.valueOf(int)ではなく、 を使用する場合にのみ発生しますnew Integer(int)。あなたが使用するオートボクシングはInteger.valueOf.

JLSによると、-128 から 127 までの値の場合、オートボクシング後に同一の Integer オブジェクトが得られるという事実をいつでも当てにできます。一部の実装では、より高い値でも同一のオブジェクトが得られる可能性があります。

実際、Java 7 (および Java 6 の新しいバージョンではそう思います) では、IntegerCache クラスの実装が変更され、上限はハードコーディングされなくなりましたが、プロパティ "java.lang.Integer.IntegerCache.高」であるため、VM パラメーターを使用してプログラムを実行すると、-Djava.lang.Integer.IntegerCache.high=1000すべての値に対して「同じ値」が得られます。

しかし、JLS は 127 までしか保証しません。

理想的には、指定されたプリミティブ値 p をボックス化すると、常に同一の参照が生成されます。実際には、これは既存の実装技術を使用して実現できない場合があります。上記のルールは実用的な妥協案です。上記の最後の節では、特定の共通値を常に区別できないオブジェクトにボックス化する必要があります。実装は、遅延または積極的にこれらをキャッシュする場合があります。

他の値については、この定式化により、プログラマー側でボックス化された値の同一性に関する仮定ができなくなります。これにより、これらの参照の一部またはすべてを共有できます (必要ではありません)。

これにより、ほとんどの一般的なケースで、特に小さなデバイスで過度のパフォーマンスのペナルティを課すことなく、動作が望ましいものになることが保証されます。メモリ制限の少ない実装では、たとえば、-32K ~ +32K の範囲の整数と長整数だけでなく、すべての文字と短整数をキャッシュする場合があります。

于 2013-02-22T13:07:11.823 に答える
6

Java 言語仕様によると:

ボックス化される値 p が true、false、バイト、\u0000 ~ \u007f の範囲の char、または -128 ~ 127 の int または short の数値である場合、r1 と r2 は任意の 2 つのボックス化変換の結果とします。 pの。r1 == r2 は常にそうです。

JLS ボクシング コンバージョン

int キャッシングの詳細については、この記事を参照してください。

于 2013-02-22T13:05:53.643 に答える
6

Integerのラッパークラスですint

Integer != Integer値を比較する場所で、実際のオブジェクト参照int != intを比較します。

既に述べたように、値 -128 から 127 はキャッシュされるため、それらに対して同じオブジェクトが返されます。

その範囲外の場合、別のオブジェクトが作成されるため、参照が異なります。

それを修正するには:

  • 型を作っintたり
  • int型をorにキャストする
  • 使用する.equals()
于 2013-02-22T13:08:14.427 に答える
4

Integer オブジェクトには内部キャッシュ メカニズムがあります。

private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer's autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

valueOf メソッドも参照してください。

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

valueOfこれが、代わりに を使用する必要がある理由ですnew Integer。オートボクシングはこのキャッシュを使用します。

この投稿も参照してください: https://effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/

equals を使用==して値を比較することはお勧めできません。

于 2013-02-22T13:11:57.523 に答える
2

.equals()の代わりに使用し==ます。

整数値は、最も頻繁に使用されるため、-127 から 128 までの数値に対してのみキャッシュされます。

if (a.equals(b)) { ... }
于 2013-02-22T13:06:42.927 に答える
1

インスタンスの取得方法によってはInteger、どの値でも機能しない場合があります。

System.out.println(new Integer(1) == new Integer(1));

版画

false

これは、==参照型のオペランドに適用される演算子が、それらのオペランドが表す値とは関係がないためです。

于 2013-02-22T13:15:48.480 に答える
0

これは、Integerクラスの実装ロジックのためです。128 までの数値用のオブジェクトを用意しています。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Integer.javaソースのオープンをチェックアウトできます。 -jdk など (cache[] を検索)。基本的に、Enum を 1 つ例外として、
オブジェクトを比較するべきではありません。==

于 2013-02-22T13:12:27.943 に答える