8

Looking at this example code similar to this question:

public class A {
    public static void main(String args[]){
        A a = new A();
        System.out.println(a.equals((a = null)));
    }
}

This prints false. Why doesn't it fail with a NullPointerException? The assignment has to get processed before the equals method can run, but somehow that doesn't affect the reference that equals is called on until after the whole line is evaluated?

I didn't see where in the Java language spec it describes this, did I miss it somewhere?

Community
  • 1
  • 1
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276

2 Answers2

9

From JLS:

At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated. Third, the accessibility of the method to be invoked is checked. Fourth, the actual code for the method to be executed is located. Fifth, a new activation frame is created, synchronization is performed if necessary, and control is transferred to the method code.

This shows that in a.equals((a = null)). the following steps occur:

  1. a's reference is computed. This is sometimes called "binding the method call".
  2. a=null is evaluated as part of evaluating arguments. It does not affect step 1.
  3. The accessibility of equals(Object) is checked.
  4. JVM internal code finds the actual bytecode.
  5. Invocation occurs

Clearly, the reference of a is determined before a is nulled, averting an NPE.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
nanofarad
  • 40,330
  • 4
  • 86
  • 117
  • One question, why "may be" , is it cause perhaps it's was calculated before? or something else? – nachokk May 23 '14 at 18:54
  • @nachokk To be honest, I'm not 100% sure on this. I'd assume it's so that JIT can optimize method calls more aggressively. What is clear is that it can't be calculated afterwards. – nanofarad May 23 '14 at 18:55
  • I wonder why the Java language works on resolving arguments and binds the call before it checks accessibility. Seems like it'd be more efficient to check accessibility first so that the work in steps 1&2 aren't done until we know well actually use it. – Andrew Gies May 23 '14 at 22:13
  • Accessibility may be based on runtime info such as the declared and actual types of the object reference, and the parameters. – nanofarad May 23 '14 at 22:15
  • @nachokk I think the docs say *may be* because of static methods which don't need a target. – Yogu May 23 '14 at 22:19
2

I believe the section of the JLS you are interested in is

15.12.4. Run-Time Evaluation of Method Invocation

At run time, method invocation requires five steps. First, a target reference may be computed. Second, the argument expressions are evaluated

Thus, the evaluation of the target occurs while a still has a non-null value, THEN a is set to null as the argument to the method invocation. So the equals method is invoked with a this reference to the object formerly known as a, which still exists, with a null argument.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190