According to the JLS, runtime evaluation of an array access expression behaves as follows:
- First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated.
- Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
- Otherwise, if the value of the array reference expression is null, then a NullPointerException is thrown.
So this code will print: java.lang.NullPointerException, index=2
class Test3 {
public static void main(String[] args) {
int index = 1;
try {
nada()[index = 2]++;
} catch (Exception e) {
System.out.println(e + ", index=" + index);
}
}
static int[] nada() {
return null;
}
}
The question is: for what reason do we need to first evaluate the index = 2
expression and not just throw the NullPointerException once the array reference is evaluated to null? Or in other words - why is the order 1,2,3 and not 1,3,2?
An array access expression has two sub-expressions:
An array access expression contains two subexpressions, the array reference expression (before the left bracket) and the index expression (within the brackets).
The two sub-expressions are evaluated before the array access expression itself, in order to evaluate the expression.
After evaluating the two sub-expressions
nada()[index = 2]++;
becomes
null[2]++;
Only now the expression is evaluated and the NullPointerException
is thrown.
This is consistent with the evaluation of most expressions in Java (the only counter examples I can think of are short circuiting operators such as && and ||).
For example, if you make the following method call:
firstMethod().secondMethod(i = 2);
First you evaluate firstMethod()
and i = 2
, and only later you throw NullPointerException
if firstMethod()
evaluated to null
.