Search code examples
javatypestype-conversioninteger-arithmetic

Binary addition performs type boundary checking whereas shorthand and increment doesn't


I see that the below code:

byte b = 127;
b = b + 1;
b = b + 1;
System.out.println(b);

leads to boundary checking during runtime, and the first addition takes b out of range, leading to following error -

Main.java:11: error: incompatible types: possible lossy conversion from int to byte b=b+1; Main.java:12: error: incompatible types: possible lossy conversion from int to byte b=b+1;

However, when I use the shorthand or increment, as:

byte b = 127;
b += 1;
b++;
System.out.println(b);

we find that the value of byte 'wraps around', giving the output

-127

Why this anomaly? What actually prevents the addition from wrapping around(as C does), or increment/shorthand from doing boundary checks?


Solution

  • Why this anomaly?

    When you add a byte plus an int you get an int so when you assign it to a byte it complains. However when you do

    b += 1;
    

    There is an implicit cast in this operation which is not obvious but is in the JLS. A clearer example is

    char ch = '0';
    ch /= 0.9; // << an implicit cast occurs here.
    System.out.println(ch); // 5
    

    similarly, when you do

    b++;
    

    for this to compile, it has to assume an overflow is possible.

    In short, the difference is that

    b = b + 1;
    

    has two operators instead of one, and this results in a warning that an overflow might occur.

    Note: This doesn't apply to int or long types as you can do

    int i = Integer.MAX_VALUE;
    i = i + 1; // no warning as int is not widened to long
    long l = Long.MAX_VALUE;
    l = l + 1; // no warning as long is the widest type.
    

    Even if Java 10 might have Long2 for 128 bit integers (and it might) long still won't be widened.