This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Closed 6 years ago.
This Java code
public class test{
public static void main(String[] args){
byte[] a = new byte[1];
a[0] = 1;
byte x = 1;
x = x + a[0];
System.out.println(x);
}
}
throws the following compile error:
test.java:10: possible loss of precision
found : int
required: byte
byte y = x + a[0];
^
1 error
huh? What is going on here? all variables are declared as byte. Explicitly casting the 1's to byte doesn't make any difference. However, change to
public class test{
public static void main(String[] args){
byte[] a = new byte[1];
a[0] = 1;
byte x = 1;
x += a[0];
System.out.println(x);
}
}
and everything compiles fine. I'm compiling with java version 1.6.0_16, build-b01. My questions are: Is this a bug or a feature? Why does += perform differently than + ?
You will find this answer of great help.
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.
Notice the explicit cast that is introduced when using the compound assignment operator.
In the first case the result is int. so you need to cast it explicitly for byte. But in the second case, java will convert the value automatically to byte. So casting is not needed and no exception.
This is the result of a quirk in the Java Language Specification. The default type of an integral expression (such as x + a[0]) is int, and the compiler then complains when you try to assign the result to a byte without a cast. Technically speaking, of course, it's correct, and you could easily overflow the byte precision. Using the += syntax avoids the separate x + a[0] expression and its implicit widening conversion:
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.
Related
This question already has answers here:
Why don't Java's +=, -=, *=, /= compound assignment operators require casting?
(11 answers)
Closed 7 months ago.
Consider the following piece of code:
class Converter {
public static void main(String args[]) {
byte num = 1;
num = num * 2.5;
System.out.println("Result is: " + num);
}
}
The compiler throws the following error:
error: incompatible types: possible lossy conversion from double to the byte at line 1
If I change the second line of the main() method and I use the *= shorthand operator:
class Converter {
public static void main(String args[]) {
byte num = 1;
num *= 2.5;
System.out.println("Result is: " + num);
}
}
The code compiles and runs successfully with the output:
Result is: 2
Why the *= shorthand operator is behaving differently from the full expression num = num * 2.5?
From the JLS compound assigment operator documentation, you can see the following example :
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);
It simply auto cast the result by default.
PS : In this other answer I tried to explain the reason you need to cast an operation like the following using the JLS
short x = 3;
x = x + 1; //Won't compile
It is realativly new so I am open to suggestion there.
According to java language specification "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.
And you can saw bytecode of your example after compilation(check instruction 3-10).
3: i2d //convert an int into a double
4: ldc2_w #2 // double 2.5d
7: dmul //multiply two doubles
8: d2i // convert a double to an int
9: i2b //convert an int into a byte
10: istore_1 //store int value into variable 1
As already said by AxelH it is a compound assignement but I would like to uderline this:
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.
That means that by definition it is casting the result. For example:
byte b = 1;
b *= 2.3;
System.out.println(b); // prints 2
From your comment:
So can I say that shorthand operator suppresses the lossy conversion
error and simply does what input it has?
No, you can't. It's not suppressing any error because there is no error in casting (in this context).
I've found that java compile has a non-expected behavior regarding assignment and self assignment statements using an int and a float.
The following code block illustrates the error.
int i = 3;
float f = 0.1f;
i += f; // no compile error, but i = 3
i = i + f; // COMPILE ERROR
In the self assignment i += f the compile does not issue an error, but the result of the exaluation is an int with value 3, and the variable i maintains the value 3.
In the i = i + f expression the compiler issues an error with "error: possible loss of precision" message.
Can someone explain this behavior.
EDIT: I've posted this code block in https://compilr.com/cguedes/java-autoassignment-error/Program.java
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2
The Java Language Specification says:
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.
So i += f is equivalent to i = (int) (i + f).
i believe that the explicit i+f fails because of Narrowing primitive conversion. While in the first case the conversion on the right side passes because it is done according to Compound Assignment rules.
I have been working with Java's byte primitive lately, and I came across a silly problem:
byte a = 10;
byte b = 9;
byte c = 8;
b += b*c; // how come this statement is correct without any explicit type casting
b = b*c; // while this statement is incorrect; it requires explicit cast, of course
b = b+(b*c); // this is wrong too.
So my question is, does += specify any assignment other than just add and assign, or is this a bug in Java (which I am almost sure is not)?
Because b += b*c is equivalent to b += (byte) ((b) + (b*c)).
From the Java language specification on 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.
All compound assignment operators not only performs the operation, but also cast automatically their result to the type of the left-hand side variable.
So your += not only adds variables and assign the result - it also cast the result to the right type.
I've found that java compile has a non-expected behavior regarding assignment and self assignment statements using an int and a float.
The following code block illustrates the error.
int i = 3;
float f = 0.1f;
i += f; // no compile error, but i = 3
i = i + f; // COMPILE ERROR
In the self assignment i += f the compile does not issue an error, but the result of the exaluation is an int with value 3, and the variable i maintains the value 3.
In the i = i + f expression the compiler issues an error with "error: possible loss of precision" message.
Can someone explain this behavior.
EDIT: I've posted this code block in https://compilr.com/cguedes/java-autoassignment-error/Program.java
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2
The Java Language Specification says:
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.
So i += f is equivalent to i = (int) (i + f).
i believe that the explicit i+f fails because of Narrowing primitive conversion. While in the first case the conversion on the right side passes because it is done according to Compound Assignment rules.
This question already has answers here:
why byte += 1 compile but byte = byte + 1 not?
(8 answers)
Closed 6 years ago.
What happens when we try to increment a byte variable using the increment operator and also by the addition operator.
public class A {
public static void main(final String args[]) {
byte b = 1;
b++;
b = b + 1;
}
}
Please give me the source where we can find such small things unleashed? Please help me out.
The difference is that there is an implicit casting in the ++ operator from int to byte, whereas, you would have to do that explicitly in case if you use b = b + 1
b = b + 1; // Will not compile. Cannot cast from int to byte
You need an explicit cast:
b = (byte) (b + 1);
Whereas b++ will work fine. The ++ operator automatically casts the value b + 1, which is an int to a byte.
This is clearly listed in 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
Please note that operation b + 1 will give you a result of type int. So, that's why you need an explicit cast in your second assignment.
What happens? Actually b = b + 1 won't compile.
You must explicitly convert it to byte, because b + 1 evaluates to int. And it is not guaranteed that an int can fit into a byte.
b = (byte)(b + 1);
The variable will be incremented twice
b++; and b=b+1; are equivalent and will result in the same bytecode.
b will be equal to 3 before the main method is finished.
Edit: actually they are not equivalent: b=b+1; is wrong and should be b=(byte) (b+1); [cast to a byte, otherwise it is an int]