web-dev-qa-db-ja.com

Java:整数が等しい===

Java 1.5の時点では、多くの状況でIntegerintをほとんど交換できます。

しかし、コードに潜在的な欠陥があり、それが少し驚きました。

次のコード:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;

値が等しい場合、不一致を誤って設定しているように見えましたが、どのような状況で判断することはできません。 Eclipseにブレークポイントを設定し、Integer値が両方とも137であることがわかりました。ブール式を調べて、それが偽であると言いましたが、それをステップオーバーすると、ミスマッチがtrueに設定されました。

条件の変更:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))

問題を修正しました。

誰がこれが起こったのかについていくつかの光を当てることができますか?これまでのところ、自分のPCのローカルホストでのみ動作を確認しています。この特定のケースでは、コードは約20回の比較で成功しましたが、2回失敗しました。問題は一貫して再現可能です。

一般的な問題であれば、他の環境(devおよびtest)でエラーが発生するはずですが、これまでに、このコードスニペットを実行した何百ものテストの後、誰も問題を報告していません。

==を使用して2つのInteger値を比較することはまだ正当ではありませんか?

以下のすべての詳細な回答に加えて、次のstackoverflowリンクにはかなりの追加情報があります。実際には元の質問に答えていたはずですが、質問でオートボクシングについて言及していなかったため、選択した提案には表示されませんでした。

なぜコンパイラ/ JVMがオートボクシングを「正常に動作させる」ことができないのですか?

140
Jeremy Goodell

JVMは整数値をキャッシュしています。 == -128〜127の間の数値でのみ機能します http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

220
Adam

2つのIntegerを単純な==と比較することはできません。これらはオブジェクトであるため、ほとんどの場合、参照は同じではありません。

トリックがあります。Integerが-128〜127の場合、参照はオートボクシングが小さな整数をキャッシュするInteger.valueOf()を使用するのと同じになります。

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


リソース:

同じトピックについて:

70
Colin Hebert

問題は、2つのIntegerオブジェクトがまさにそのオブジェクトであるということです。 2つのオブジェクト参照を比較しているため、それらの値は一致しません。明らかに.equalsは、オブジェクト参照の比較ではなく、値の比較を提供するためにオーバーライドされます。

5
MattC

Integerは参照を参照します。つまり、参照を比較するときに、値ではなく同じオブジェクトを指している場合に比較します。したがって、あなたが見ている問題。プレーンなint型でうまく機能する理由は、Integerに含まれる値をボックス化解除するためです。

あなたがやっていることをやっているなら、なぜ最初にifステートメントがあるのでしょうか?

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );
4
wheaties

「==」は、常にメモリロケーションまたは値のオブジェクト参照を比較します。 equalsメソッドは常に値を比較します。しかし、equalsは、間接的に "=="演算子を使用して値を比較します。

整数は、整数キャッシュを使用して、-128〜+127の値を保存します。 ==演算子を使用して-128〜127の値をチェックすると、trueが返されます。これらの値以外の場合はfalseを返します。

追加情報については link を参照してください

3
vijay