views:

208

answers:

2

In Java, when you do

int b = 0;
b = b + 1.0;

You get a possible loss of precision error. But why is it that if you do

int b = 0;
b += 1.0;

There isn't any error?

+14  A: 

That's because b += 1.0; is equivalent to b = (int) ((b) + (1.0));. The narrowing primitive conversion (JLS 5.1.3) is hidden in the compound assignment operation.

JLS 15.26.2 Compound Assignment Operators:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

For example, the following code is correct:

short x = 3;
x += 4.6;

and results in x having the value 7 because it is equivalent to:

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

This also explains why the following code compiles:

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

But this doesn't:

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

You need to explicitly cast in this case:

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

It's worth noting that the implicit cast in compound assignments is the subject of Puzzle 9: Tweedledum from the wonderful book Java Puzzlers. Here are some excerpt from the book (slightly edited for brevity):

Many programmers think that x += i; is simply a shorthand for x = x + i;. This isn't quite true: if the type of the result is wider than that of the variable, the compound assignment operator performs a silent narrowing primitive conversion.

To avoid unpleasant surprises, do not use compound assignment operators on variables of type byte, short, or char. When using compound assignment operators on variables of type int, ensure that the expression on the right-hand side is not of type long, float, or double. When using compound assignment operators on variables of type float, ensure that the expression on the right-hand side is not of type double. These rules are sufficient to prevent the compiler from generating dangerous narrowing casts.

For language designers, it is probably a mistake for compound assignment operators to generate invisible casts; compound assignments where the variable has a narrower type than the result of the computation should probably be illegal.

The last paragraph is worth noting: C# is a lot more strict in this regard (see C# Language Specification 7.13.2 Compound assignment).

polygenelubricants
Thanks. It's hard to search for documentation when the keyword you want to use is something like "+=". :P
szupie
All `op=` operators are called "compound assignment" in Java. But yes, I do think that querying for symbols instead of keywords is hard in most search engines.
polygenelubricants
Any googlers here? I'd like a search box which also takes into account symbols like + = < and > :)
extraneon
Yeah, I wish there'd be a way to use regular google with regular expressions like in google code search. But then again, they'd need to change their whole indexing system.
szupie
A: 

Maybe, and just maybe it is because in the former it is converting b to floating point, then adding, then converting it back to integer ?

And the latter it may be converting 1.0 to integer instead, and doing integer addition?

Just a guess though.

Francisco Soto