Java では new Integer(i) == i であることが保証されていますか?
-
26-09-2019 - |
質問
次のスニペットを考えてみましょう。
int i = 99999999;
byte b = 99;
short s = 9999;
Integer ii = Integer.valueOf(9); // should be within cache
System.out.println(new Integer(i) == i); // "true"
System.out.println(new Integer(b) == b); // "true"
System.out.println(new Integer(s) == s); // "true"
System.out.println(new Integer(ii) == ii); // "false"
最後の行がなぜそうなるのかは明らかです いつも プリント "false"
:私たちが使っている ==
参照同一性の比較、および new
オブジェクトは 一度もない なれ ==
既存のオブジェクトに。
質問は最初の3行についてです。それらの比較ですか 保証された 原始的なものになる int
, 、 とともに Integer
自動でボックス解除されますか?代わりにプリミティブがオートボックス化され、参照同一性の比較が実行される場合はありますか?(そうすると、すべてが false
!)
解決
はい。 JLS §5.6.2 バイナリ数値の昇格のルールを指定します。ある程度:
演算子がバイナリを適用する場合 のペアへの数値の上位変換 オペランドで、それぞれが 数値に変換できる値 type の場合、次のルールが適用されます。 順序、拡大変換の使用[じゅうじゅう、拡大変換の (§5.1.2) を使用してオペランドを いる:
オペランドのいずれかが参照タイプの場合、ボクシング変換(§5.1.8)が実行されます。
バイナリ数値昇格は、「数値等価演算子 == および !=」を含むいくつかの数値演算子に適用されます。
JLS §15.21.1 (数値等価演算子 == および !=) は以下を指定します。
等価のオペランド 演算子が両方とも数値型である、または 1 つは数値型で、もう 1 つは (§5.1.8) を数値に変換できます。 type、バイナリ数値の上位変換は オペランド (§5.6.2) で実行されます。
対照的に、 JLS §15.21.3 (参照等価演算子 == および !=) は以下を提供します。
平等演算子のオペランドが参照タイプまたはnullタイプのいずれかである場合、操作はオブジェクトの平等です
これは、ボックス化とアンボックス化についての一般的な理解、つまり不一致がある場合にのみ実行されるというものと一致します。
他のヒント
まず説明します まさにいつ ==
は参照等価であり、 まさにいつ それは数値上の等価性です。参照等価の条件は簡単なので先に説明します。
JLS 15.21.3 参照等価演算子 ==
そして !=
等価演算子のオペランドが両方とも参照型または ヌル type の場合、操作はオブジェクトの等価性です。
これにより、次のことが説明されます。
System.out.println(new Integer(0) == new Integer(0)); // "false"
両方のオペランドは、 Integer
, 、これらは参照型であるため、 ==
は参照の等価比較、および 2 new
オブジェクトは決して存在しません ==
お互いに、だから印刷されるのです false
.
のために ==
数値的に等しくなるには、 オペランドの少なくとも 1 つは数値型である必要があります;これは次のように指定されます。
JLS 15.21.1 数値等価演算子 ==
そして !=
等価演算子のオペランドが 両方 数値型、または 一つは 数値型と もう一方はコンバーチブルです 数値型に変換すると、オペランドに対してバイナリ数値の昇格が実行されます。オペランドのプロモートされた型が
int
またはlong
, 、その後、整数の等価性テストが実行されます。プロモートされたタイプが次の場合float or
double` を指定すると、浮動小数点の等価性テストが実行されます。バイナリ数値プロモーションでは、値セット変換とアンボックス化変換が実行されることに注意してください。
したがって、次の点を考慮してください。
System.out.println(new Integer(0) == 0); // "true"
これは印刷します true
, 、 なぜなら:
- 右オペランド は 数値
int
タイプ - 左オペランド に変換可能です 数値型。ボックス化を解除すると、
int
- したがって
==
数値等価演算です
まとめ
- 両方のオペランドが
==
そして!=
参照型である場合、常に参照等価演算になります。- オペランドが数値型に変換可能かどうかは関係ありません
- オペランドの少なくとも 1 つが数値型の場合、常に数値等価演算になります。
- 必要に応じて、オペランドの 1 つ (最大でも!) の自動アンボックス化が実行されます。
参考文献
- JLS4.2。プリミティブの型と値
- 「 数値型 整数型と浮動小数点型です。」
- Java 言語ガイド/オートボクシング
- JLS 5.1.8 ボックス化解除変換
- JLS 15.21.1 数値等価演算子
==
そして!=
- JLS 15.21.3 参照等価演算子
==
そして!=
- JLS 5.6.2 バイナリ数値プロモーション