By Andrei Nepsha


2019-03-14 11:00:56 8 Comments

According to the JLS, runtime evaluation of an array access expression behaves as follows:

  1. 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.
  2. Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
  3. 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?

4 comments

@Michael 2019-03-14 11:48:21

The decision may be partially be rooted in performance.

In order to know that index = 2 is not going to be required, we would have to first evaluate nada() and then check whether it was null. We would then branch on the result of this condition, and decide whether or not to evaluate the array index expression.

Every perfectly valid array index expression would be made slower by one additional operation, just for the sake of saving code - code that is going to throw an exception anyway - from evaluating one expression unnecessarily.

It is an optimistic approach which works better in the majority of cases.

@Joop Eggen 2019-03-14 11:35:59

The basic byte code operations are (for an int[])

ALOAD array_address
ILOAD index
IALOAD array_element_retrieval

The IALOAD does the null pointer check. In reality the code is a bit more elaborate:

  1. calculate array address
  2. calculate index
  3. IALOAD

So the answer is: it would need an extra checking operation after the array address is loaded, in anticipation of the array access.

Behavior by straight implementation.

@Eran 2019-03-14 11:30:34

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.

@Thomas Kläger 2019-03-14 11:27:28

This is because in the generated bytecode there are no explicit null checks.

nada()[index = 2]++;

is translated into the following byte code:

// evaluate the array reference expression
  INVOKESTATIC Test3.nada ()[I
// evaluate the index expression
  ICONST_2
  DUP
  ISTORE 1
// access the array
// if the array reference expression was null, the IALOAD operation will throw a null pointer exception
  DUP2
  IALOAD
  ICONST_1
  IADD
  IASTORE

Related Questions

Sponsored Content

5 Answered Questions

[SOLVED] Checking if a string is empty or null in Java

  • 2013-02-06 04:12:07
  • user2027811
  • 666850 View
  • 267 Score
  • 5 Answer
  • Tags:   java

2 Answered Questions

7 Answered Questions

[SOLVED] Is null check needed before calling instanceof?

1 Answered Questions

[SOLVED] Why does array[idx++]+="a" increase idx once in Java 8 but twice in Java 9 and 10?

2 Answered Questions

[SOLVED] NullPointerException when switching activites and using a global array

1 Answered Questions

[SOLVED] Runtime evaluation of expressions in Java method references

9 Answered Questions

[SOLVED] Checking for a null int value from a Java ResultSet

  • 2010-05-27 10:42:19
  • ian_scho
  • 215367 View
  • 246 Score
  • 9 Answer
  • Tags:   java null resultset

7 Answered Questions

[SOLVED] Why can I throw null in Java?

2 Answered Questions

Printing an array with no elements?

  • 2015-04-21 06:24:13
  • Hatz
  • 713 View
  • 1 Score
  • 2 Answer
  • Tags:   java arrays

Sponsored Content