質問

Javaで、あなたがそうするとき

int b = 0;
b = b + 1.0;

精密エラーの損失の可能性があります。しかし、なぜそうするなら

int b = 0;
b += 1.0;

エラーはありませんか?

役に立ちましたか?

解決

それはだからです 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)), 、 どこ t のタイプです E1, 、 それ以外で E1 一度だけ評価されます。

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

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!

複合割り当ての暗黙のキャストがの主題であることは注目に値します パズル9:Tweedledum 素晴らしい本から Java Puzzlers. 。本からの抜粋を次に示します(Brevityのためにわずかに編集):

多くのプログラマーはそれを考えています x += i; 単に速記です x = x + i;. 。これはまったく真実ではありません。結果のタイプが変数のタイプよりも広い場合、複合割り当て演算子はサイレント狭窄の原始変換を実行します。

不快な驚きを避けるために、 タイプの変数に複合割り当て演算子を使用しないでください byte, short, 、 また char. 。タイプの変数で複合割り当て演算子を使用する場合 int, 、右側の式がタイプでないことを確認してください long, float, 、 また double. 。タイプの変数で複合割り当て演算子を使用する場合 float, 、右側の式がタイプでないことを確認してください double. 。これらのルールは、コンパイラが危険な狭窄キャストを生成するのを防ぐのに十分です。

言語デザイナーにとって、おそらく複合割り当てオペレーターが目に見えないキャストを生成することは間違いです。変数が計算の結果よりも狭いタイプを持っている複合割り当ては、おそらく違法である必要があります。

最後の段落は注目に値します。C#はこの点ではるかに厳格です(参照 C#言語仕様7.13.2化合物の割り当て).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top