11

次のコードは、2 つの異なる出力を提供するため、非常にわかりにくいように思われました。コードは jdk 1.7 でテストされています。

public class NotEq {

public static void main(String[] args) {

    ver1();
    System.out.println();
    ver2();
}

public static void ver1() {
    Integer a = 128;
    Integer b = 128;

    if (a == b) {
        System.out.println("Equal Object");
    }

    if (a != b) {
        System.out.println("Different objects");
    }

    if (a.equals(b)) {
        System.out.println("Meaningfully equal.");
    }
}

public static void ver2() {
    Integer i1 = 127;
    Integer i2 = 127;
    if (i1 == i2) {
        System.out.println("Equal Object");
    }

    if (i1 != i2){
        System.out.println("Different objects");
    }
    if (i1.equals(i2)){
        System.out.println("Meaningfully equal");
    }
}

}

出力:

[ver1 出力]
異なるオブジェクト
意味的に等しい。

[ver2 出力]
等しいオブジェクト
意味的に等しい

== と != のテストで、Integer.MAX_VALUE よりもはるかに小さい同じ数値に対して、ver1() と ver2() の結果が異なるのはなぜですか? == 127 より大きい数値 (コードに示されているように Integer のようなラッパー クラスの場合) をチェックすることは、完全に時間の無駄であると結論付けることができますか?

4

5 に答える 5

10

整数は -128 ~ 127 の値に対してキャッシュされるため、Integer i = 127常に同じ参照が返されます。Integer j = 128必ずしもそうするわけではありません。equals次に、基になる が等しいかどうかをテストするために を使用する必要がありますint

これはJava 言語仕様の一部です:

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

ただし、 を 2 回呼び出すとInteger j = 128、同じ参照が返される場合があります (保証されません)。

メモリ制限の少ない実装では、たとえば、すべての char 値と short 値、および -32K から +32K の範囲の int 値と long 値をキャッシュする場合があります。

于 2012-03-22T14:17:01.337 に答える
4

小さな整数はJavaでインターンされているため、「小ささ」の制限のさまざまな側で数値を試しました。

于 2012-03-22T14:16:02.830 に答える
3

デフォルトでは、-128 から 127 までの整数オブジェクト キャッシュが存在します。上枠を設定できます。上部キャッシュ境界は VM オプションで制御できます-XX:AutoBoxCacheMax=<size>

フォームを使用する場合、このキャッシュを使用しています:

 Integer i1 = 127;

また

Integer i1 = Integer.valueOf(127);

でも使うときは

Integer i1 = new Integer(127);

その後、キャッシュされていない新しいオブジェクトを取得することが保証されます。後者の場合、両方のバージョンで同じ結果が出力されます。キャッシュされたバージョンを使用すると、異なる場合があります。

于 2012-03-22T14:24:33.740 に答える
0

Java は -128 から 127 までの整数をキャッシュします。これが、オブジェクトが同じである理由です。

于 2012-03-22T14:18:01.800 に答える
0

プリミティブを扱うときの == および != 演算子は、現在使用している方法で機能すると思いますが、オブジェクト (Integer と int) では、.equals() メソッドでテストを実行する必要があります。

これについては確信が持てませんが、オブジェクトを使用すると、== は 1 つのオブジェクトが同じオブジェクトであるかどうかをテストし、.equals() はこれら 2 つのオブジェクトの値が等しいかどうかをテストします (または、メソッドがカスタム オブジェクトの作成/オーバーライド)。

于 2012-03-22T14:19:26.087 に答える