Why does string 1 fail with a compilation error, but line 2 does not?

public class text { public static void main(String[] args) { byte b1 = 127; b1 = b1 + 1; // 1 b1 += 1; // 2 } } 
  • b1 = b1 + 1 here, in the right part, actions in the format int numbers take place. In the second case, you call the + = operator, which works with the arithmetic of the left argument (in your case, byte). In general, for integers, any operations +, -, *, / primarily behave exactly like an int. And at your request, you can do something like b1 = (byte) (b1 + 1), which will correct the error. - test123
  • those. abbreviated operations like + = work with the left operand arithmetic and are valid, right? - basketplayer
  • This is a separate statement. In this case, it behaves equivalently to a + = 1 <=> a = a + 1. In other languages, it can be overloaded and behave as you like. Yes that's right. - test123

2 answers 2

For addition in the JVM there are 4 opcodes - iadd, ladd, fadd and dadd. For types integer, long, float and double, respectively. Therefore, the addition of two bytes will be compiled into

 iload_1 iload_2 iadd istore_3 

That is, the operands will be loaded into the stack as integers, and the result of the addition will return as an integer. And an attempt to keep an integer in byte without an explicit conversion can lead to overflow. What the compiler warns about.

This behavior is fixed in JLS 5.6.2 :

The following rules apply, in the following rules apply, in order:

  • This is a reference to unboxing conversion (§5.1.8).
  • Widening primitive conversion (§5.1.2) is the following rules:
  • If either is converted to double.
  • Otherwise, if either is converted to float.
  • Otherwise, if either the operand is of type long, the other is converted to long.
  • Otherwise, both operands are converted to type int.

Operation b1 += 1; will be compiled into

 iload_1 iconst_1 iadd i2b istore_1 

Interesting here is the i2b opcode - a conversion from integer to byte. That is, the compiler does implicit type casting.

And this behavior is fixed in JLS 15.26.2 :

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.

    See the Compound Assignment Operators documentation.

    Here the output of 'b1 + = 1' is interpreted in 'b1 = (byte) b1 + 1'