Consider the following code:
int[] r = null;
r[0] = 1 % 0;
I would have expected this to throw a NullPointerException
: according to JLS Sec 15.7.1:
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
=
is a binary operator (shown in JLS Sec 15.2 - JLS Sec 15.26 describes assignment operators), and fully-evaluating the left-hand operand will result in a NullPointerException
. However, an ArithmeticException
is thrown, indicating that the right-hand operand is evaluated before the left-hand operand is fully evaluated.
Why?
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 toE1 = (T) ((E1) op (E2))
, whereT
is the type ofE1
, except thatE1
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.
来源:https://stackoverflow.com/questions/42854455/why-doesnt-an-array-access-expression-of-a-null-array-reference-throw-a-nullpoi