web-dev-qa-db-ja.com

等号演算子が128までの整数値で機能するのはなぜですか?

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

これは私のJava環境:Javaバージョン"1.6.0_37"

Java(TM)SEランタイム環境(ビルド1.6.0_37-b06)

Java HotSpot(TM)64ビットサーバーVM(ビルド20.12-b01、混合モード)

サンプルコード:

    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

ありがとう!

25
gokhansari

Integerのソースコード を確認してください。そこで値のキャッシュを見ることができます。

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

[〜#〜] jls [〜#〜] によると、-128から127までの値の場合、オートボクシング後に同一のIntegerオブジェクトを取得し、一部では実装では、より高い値でも同じオブジェクトを取得する場合があります。

実際にはJava 7(そして、私はJava 6)の新しいバージョンで考える)で、IntegerCacheクラスの implementation が変更され、上限はハードコードされなくなりましたが、プロパティ「Java.lang.Integer.IntegerCache.high」を介して構成できるため、VMパラメータ-Djava.lang.Integer.IntegerCache.high=1000、すべての値で「同じ値」を取得します。

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

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

他の値の場合、この定式化は、プログラマー側のボックス化された値の同一性に関する想定を許可しません。これにより、これらの参照の一部またはすべてを共有できるようになります(必須ではありません)。

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

23
lbalazscs

Java言語仕様:

ボックス化される値pがtrue、false、バイト、\ u0000から\ u007fの範囲の文字、または-128から127までの整数または短い数値である場合、r1とr2を2つのボックス化変換の結果とするの常にr1 == r2です。

JLSボクシング変換

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

6
Denis Rosca

Integerintのラッパークラスです。

_Integer != Integer_は実際のオブジェクト参照を比較し、_int != int_は値を比較します。

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

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

修正するには:

  • タイプをintまたは
  • タイプをintにキャストするか、
  • .equals()を使用します
6
Dukeling

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);
}

このため、new IntegerではなくvalueOfを使用する必要があります。オートボクシングはこのキャッシュを使用します。

この投稿もご覧ください: https://effective-Java.com/2010/01/Java-performance-tuning-with-maximizing-integer-valueofint/

==の使用はお勧めできません。値を比較するには、equalsを使用してください。

3

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

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

_if (a.equals(b)) { ... }
_
2
Doorknob

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

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

プリント

false

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

1
Marko Topolnik

これは、Integerクラスの実装ロジックが原因です。 128までの数のオブジェクトを準備しました。チェックアウトできます http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14/Java/lang/Integer。 Java たとえば、open-jdkのソース(cache []を検索)。
基本的に、オブジェクトは==を使用して比較しないでください。ただし、Enumは例外です。

0
sandrstar