x = x*0.90; gives lossy conversion error. x*=0.90; does not. Why?

2.4k views Asked by At

I have written the code:

int x = 18;
x *= 0.90; 
System.out.println(x);

This code printed 16

However, when I wrote

int x = 18;
x = x * 0.90; 
System.out.println(x);

it gave me the following error: incompatible types: possible lossy conversion from double to int

I expected both of these code examples to result in the exact same error as x *= y; is the same as x = x * y;, but x *= 0.90; somehow works and x = x * 0.90; does not. Why is this the case?

3

There are 3 answers

10
rzwitserloot On BEST ANSWER

Because the Java Language Specifcation (JLS) says so. It's a bit odd, but, when using the compound assignment operators (*=, +=, etcetera), the cast is implied.

See JLS §15.26.2 which clearly shows the cast in the example right at the top of that section.

Why does it do that? Well, I don't think SO is the right place to ask 'what were the designers thinking 30 years ago when this part of the JLS spec was written up'.

EDIT: This answer used to mention 'probably because of C' but as comments show, no, in C neither form requires an explicit cast.

0
Golam Rabbi On

*The compound assignment operator x = 0.90; is designed to be shorter and to handle type conversion implicitly and it's helping to avoid potential lossy conversion errors.

  • Example 1: Lossy conversion error with explicit assignment

x = 5 # Assume x is an integer

x = x * 0.90 # Error: lossy conversion from float to int

  • Example 2: No error with compound assignment

x = 5 # Assume x is an integer

x *= 0.90 # No error: implicit conversion handled by the compound assignment

0
supercat On

The designers of Java generally valued consistency over the sensibility of particular cases. Given byte a,b; int i;, the expression a & b will be evaluated by converting the operands to int, and would thus yield a result type of int. There was thus no nice way to require a cast for a = (byte)i; but not require one for a = (byte)(a & b);. If the expression were written as a &= b;, there would have been no way to cast the result of the & operator before performing the assignment. Rather than make the &= (and other compound assignment) operators useless with byte, short, or char, Java opted to instead include an implicit conversion between the result of the combining operator and the use of the result for the assignment.