The specification of the simple assignment operator describes this behavior:
...
If the left-hand operand is an array access expression (ยง15.10.3), possibly enclosed in one or more pairs of parentheses, then:
- First, the array reference subexpression of the left-hand operand array access expression is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the index subexpression (of the left-hand operand array access expression) and the right-hand operand are not evaluated and no assignment occurs.
This completes normally.
- Otherwise, the index subexpression of the left-hand operand array access expression is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and the right-hand operand is not evaluated and no assignment occurs.
This completes normally.
- Otherwise, the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.
This completes abruptly, with ArithmeticException
.
- Otherwise, if the value of the array reference subexpression is null, then no assignment occurs and a NullPointerException is thrown.
This is never executed.
So, it appears that there is inconsistency - or over-simplification, at least - in the quote from Sec 15.7.1.
Interestingly, the same behavior is not observed for the compound assignment operators, e.g.
int[] arr = null;
arr[0] += 1 % 0;
does yield a NullPointerException
.
JLS Sec 15.26.2 describes this. It's perhaps less surprising, though, because:
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.
In other words, this code is (roughly) equivalent to:
arr[0] = arr[0] + 1 % 0;
so the NullPointerException
occurs in evaluating the right hand operand of the simple assignment.