Search code examples
javainteger-overflowcompound-assignment

Why doesn't compound assignment in Java catch overflow problems?


To my shock, it turns out that the following code will compile without even warnings:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value += increment;
}

Whereas this gives a compile-time error, as you would expect:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value = value + increment;
}

I checked it up and indeed, the JLS (section 15.26.2) has this to say:

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.

This seems ridiculous to me. Why did they feel the need to explicitly cast here? It seems that automatic type conversion would have handled the widening anyway, and automatically narrowing like this is pretty much guaranteed to result in integer overflow.


Solution

  • Here is one explanation:

    When you do an assignment (the first code snippet), java enforces type checking because the LHS and RHS may very well be independent of each other.

    But the compound-operator is more like an incremental operator. The += modifies the value of the variable involved, rather than assigning a new value to the variable. When you modify a byte, you expect a byte as the result. To make life easier, java does an implicit type conversion for compound-operators because they are modifiers.