31

Javaでは、あなたがするとき

int b = 0;
b = b + 1.0;

精度エラーが発生する可能性があります。しかし、なぜあなたがそうするなら

int b = 0;
b += 1.0;

エラーはありませんか?

4

1 に答える 1

35

b += 1.0;と同等だからですb = (int) ((b) + (1.0));縮小プリミティブ変換 (JLS 5.1.3)は、複合代入演算に隠されています。

JLS 15.26.2 複合代入演算子(JLS 第 3 版):

E1 op= E2の形式の複合代入式は、E1 = (T)((E1) op (E2))と同等です。ここで、TE1の型ですが、E1は 1 回だけ評価されます。

たとえば、次のコードは正しいです。

short x = 3;
x += 4.6;

次と同等であるためx、値が得られます。7

short x = 3;
x = (short)(x + 4.6);

これは、次のコードがコンパイルされる理由も説明しています。

byte b = 1;
int x = 5;
b += x; // compiles fine!

しかし、これはしません:

byte b = 1;
int x = 5;
b = b + x; // DOESN'T COMPILE!

この場合、明示的にキャストする必要があります。

byte b = 1;
int x = 5;
b = (byte) (b + x); // now it compiles fine!

複合代入での暗黙的なキャストは、すばらしい本Java PuzzlersのPuzzle 9: Tweedledumの主題であることに注意してください。本からの抜粋です(簡潔にするために少し編集されています):

多くのプログラマーは、これx += i;は単に の省略形だと考えていx = x + i;ます。これは正しくありません。結果の型が変数の型よりも広い場合、複合代入演算子は暗黙の縮小プリミティブ変換を実行します。

不愉快な驚きを避けるために、型、、またはの変数に複合代入演算子を使用しない でください。タイプ の変数で複合代入演算子を使用する場合は、右側の式がタイプ、、またはでないことを確認してください。タイプ の変数で複合代入演算子を使用する場合は、右側の式が タイプ でないことを確認してください。これらの規則は、コンパイラが危険な縮小キャストを生成するのを防ぐのに十分です。byteshortcharintlongfloatdoublefloatdouble

言語設計者にとって、複合代入演算子が目に見えないキャストを生成するのはおそらく間違いです。変数が計算の結果よりも狭い型を持つ複合代入は、おそらく不正であるはずです。

最後の段落は注目に値します。C# は、この点でより厳密です ( C# 言語仕様 7.13.2 複合代入を参照)。

于 2010-04-23T07:12:44.053 に答える