Categories
assignment-operator casting java operators variable-assignment

Why don’t Java’s +=, -=, *=, /= compound assignment operators require casting?

3791

Until today, I thought that for example:

i += j;

Was just a shortcut for:

i = i + j;

But if we try this:

int i = 5;
long j = 8;

Then i = i + j; will not compile but i += j; will compile fine.

Does it mean that in fact i += j; is a shortcut for something like this
i = (type of i) (i + j)?

15

  • 152

    I’m surprised Java allows this, being a stricter language than its predecessors. Errors in casting can lead to critical failure, as was the case with Ariane5 Flight 501 where a 64-bit float cast to a 16-bit integer resulted in the crash.

    – SQLDiver

    Jan 5, 2015 at 16:31


  • 129

    In a flight control system written in Java, this would be the least of your worries @SQLDiver

    – Ross Drew

    Nov 2, 2015 at 9:24

  • 10

    Actually i+=(long)j; even will compile fine.

    Mar 18, 2016 at 7:45

  • 8

    The constant push by one set of developers for accuracy and another for ease of use is really interesting. We almost need two versions of the language, one that is amazingly precise and one that is easy to use. Pushing Java from both directions moves it towards being unsuitable for either group.

    – Bill K

    Sep 19, 2017 at 16:03


  • 8

    if it did require casting, where would you put it? i += (int) f; casts f before addition, so it’s not equivalent. (int) i += f; casts the result after assignment, not equivalent either. there would be no place to put a cast that would signify that you want to cast the value after adding, but before assignment.

    Oct 24, 2018 at 13:09

2540

As always with these questions, the JLS holds the answer. In this case §15.26.2 Compound Assignment Operators. An extract:

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.

An example cited from §15.26.2

[…] 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);

In other words, your assumption is correct.

2

  • 43

    So i+=j compiles as I checked myself, but it would result in loss of precision right? If that’s the case, why doesn’t it allow it to happen in i=i+j also? Why bug us there?

    Sep 22, 2012 at 6:07

  • 49

    @ronnieaka: I’m guessing that the language designers felt that in one case (i += j), it is safer to assume that the loss of precision is desired as opposed to the other case (i = i + j)

    Sep 22, 2012 at 8:31

505

A good example of this casting is using *= or /=

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

or

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

or

char ch="0";
ch *= 1.1;
System.out.println(ch); // prints '4'

or

char ch="A";
ch *= 1.5;
System.out.println(ch); // prints 'a'

4

  • 12

    @AkshatAgarwal ch is a char. 65 * 1.5 = 97.5 -> Got it?

    May 5, 2014 at 22:07

  • 90

    Yeah, but I can just see some beginner coming here, reading this, and going away thinking that you can convert any character from upper case to lower case by multiplying it by 1.5.

    May 28, 2014 at 9:25

  • 109

    @DavidWallace Any character as long as it is A 😉

    May 28, 2014 at 12:56

  • 17

    @PeterLawrey & @DavidWallace I will reveal your secretch += 32 =D

    Mar 16, 2016 at 5:29


266

Very good question. The Java Language specification confirms your suggestion.

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);

4

  • 19

    Or more fun: “int x=33333333; x+=1.0f;”.

    – supercat

    Apr 20, 2017 at 19:31

  • 5

    @supercat , what trickery is this? A widening conversion that is incorrectly rounded, followed by an addition that doesn’t actually change the result, casting to int again to produce a result that is most unexpected for normal human minds.

    – neXus

    Sep 21, 2018 at 12:33

  • 1

    @neXus: IMHO, the conversion rules should have treated double->float as widening, on the basis that values of type float identify real numbers less specifically than those of type double. If one views double as a complete postal address and float as a 5-digit postal code, it’s possible to satisfy a request for a postal code given a complete address, but it’s not possible to accurately specify a request for a complete address given just a postal code. Converting a street address to a postal code is a lossy operation, but

    – supercat

    Sep 21, 2018 at 15:05

  • 1

    …someone who needs a complete address wouldn’t generally be asking for just a postal code. Conversion from float->double is equivalent to converting US postal code 90210 with “US Post Office, Beverly Hills CA 90210”.

    – supercat

    Sep 21, 2018 at 15:07