web-dev-qa-db-ja.com

ボックス化されたLong値127と128の比較

if条件を使用して、2つのLongオブジェクトの値を比較します。これらの値が128未満の場合、if条件は正しく機能しますが、128以上の場合、比較は失敗します。

例:

Long num1 = 127;
Long num2 = 127;

if (num1 == num2) {
    // Works ok
}

上記のコードの比較は適切に機能しますが、以下のコードでは失敗します。

Long num1 = 128;
Long num2 = 128;

if (num1 == num2) {
    // Does NOT work
}

Long変数と値127より大きいの比較に問題があるのはなぜですか?変数のデータ型が長いプリミティブに変更されると、すべてのケースで比較が機能します。

96
Viraj Dhamal

TL; DR

Javaは、-128から127までのボックス化された整数インスタンスをキャッシュします。 ==を使用してvaluesではなくオブジェクトreferencesを比較しているため、キャッシュされたオブジェクトのみが一致します。 longのボックス化されていないプリミティブ値を使用するか、.equals()を使用してLongオブジェクトを比較します。

長い(しゃれを意図した)バージョン

Long変数と127より大きい値の比較に問題があるのはなぜですか?上記の変数のデータ型がプリミティブ(長い)の場合、すべての値に対してコードが機能します。

Javaは-128〜127の範囲の整数オブジェクトインスタンスをキャッシュします。それは言った:

  • N個のLong変数に値127cached)を設定すると、すべての参照によって同じオブジェクトインスタンスがポイントされます。 (N個の変数、1つのインスタンス)
  • N個のLong変数に値128not cached)を設定すると、すべての参照によってオブジェクトインスタンスがポイントされます。 (N個の変数、N個のインスタンス)

これが理由です:

Long val1 = 127L;
Long val2 = 127L;

System.out.println(val1 == val2);

Long val3 = 128L;
Long val4 = 128L;

System.out.println(val3 == val4);

これを出力します:

本当
false

127L値の場合、両方の参照(val1およびval2)がメモリ内の同じオブジェクトインスタンス(キャッシュ)を指すため、trueを返します。

一方、128値の場合、メモリにキャッシュされるインスタンスがないため、ボックス化された値の新しい割り当てに対して新しいインスタンスが作成され、2つの異なるインスタンス(val3およびval4)とそれらの比較でfalseを返します。

これは、Longプリミティブ値ではなく、2つのlongオブジェクト参照==演算子と比較しているためにのみ発生します。このCacheメカニズムがなければ、これらの比較はalwaysに失敗するため、ここでの実際の問題は、==演算子でボックス化された値を比較することです。

これらの変数をプリミティブなlong型に変更すると、これが発生しなくなりますが、Longオブジェクトを使用してコードを保持する必要がある場合は、次のアプローチでこれらの比較を安全に行うことができます。

System.out.println(val3.equals(val4));                     // true
System.out.println(val3.longValue() == val4.longValue());  // true
System.out.println((long)val3 == (long)val4);              // true

(キャストの場合でも、適切なnullチェックが必要です)

IMO、オブジェクトの比較を処理するときは、常に。equals()メソッドを使用することをお勧めします。

参照リンク:

193
everton

num1およびnum2はLongオブジェクトです。それらを比較するにはequals()を使用する必要があります。 ==比較は、JVMがプリミティブをボックス化する方法が原因で機能する場合がありますが、それに依存しないでください。

if (num1.equals(num1))
{
 //code
}
14
Nishan

Javaは、プリミティブ値を-128〜127からキャッシュします。 2つのLongオブジェクトJavaを比較するとき、内部的にそれをプリミティブ値に型キャストして比較します。しかし、127を超えると、Longオブジェクトは型カーストを取得しません。 Javaは、。valueOf()メソッドによって出力をキャッシュします。

このキャッシングは、-128〜127のByte、Short、Longで機能します。整数キャッシングでは、-128からJava.lang.Integer.IntegerCache.highまたは127のいずれか大きい方まで機能します。 Java.lang.Integer.IntegerCache.highを使用してキャッシュする必要があります)。

 For example:
    If we set Java.lang.Integer.IntegerCache.high=500;
    then values from -128 to 500 will get cached and 

    Integer a=498;
    Integer b=499;
    System.out.println(a==b)

    Output will be "true".

FloatおよびDoubleオブジェクトはキャッシュされません。

文字は0〜127のキャッシュを取得します

2つのオブジェクトを比較しています。 ==演算子は、オブジェクト参照の等価性をチェックします。以下の方法があります。

1)両方のオブジェクトをプリミティブ値に型キャストして比較する

    (long)val3 == (long)val4

2)オブジェクトの値を読み取り、比較する

    val3.longValue() == val4.longValue()

3)オブジェクト比較でequals()メソッドを使用します。

    val3.equals(val4);  
13
Jay