In section Run-Time Evaluation of Method References of the Java Language Specification, it is mentioned that:
At run time, evaluation of a method reference expression is similar to evaluation of a class instance creation expression, insofar as normal completion produces a reference to an object. Evaluation of a method reference expression is distinct from invocation of the method itself.
First, if the method reference expression begins with an ExpressionName or a Primary, this subexpression is evaluated. If the subexpression evaluates to
null
, aNullPointerException
is raised, and the method reference expression completes abruptly. If the subexpression completes abruptly, the method reference expression completes abruptly for the same reason.
And ExpressionName and Primary are defined in the method reference expression syntax:
MethodReference:
ExpressionName :: [TypeArguments] Identifier ReferenceType :: [TypeArguments] Identifier Primary :: [TypeArguments] Identifier super :: [TypeArguments] Identifier TypeName . super :: [TypeArguments] Identifier ClassType :: [TypeArguments] new ArrayType :: new
I was interested by the highlighted part and wanted to test the mentioned behavior using the below code:
public class Test {
public static void main(String[] args) {
System.out.println("Testing...");
final Person p = null;
foo(p::getName); // I was expecting an NPE here
}
private static void foo(Supplier<String> supplier) {
System.out.println(supplier);
// supplier.get(); // uncommenting this causes an NPE, but not when evaluating
// the method reference, but rather when the method is invoked.
}
static class Person {
String getName() {
return "x";
}
}
}
However, the line foo(p::getName)
does not throw a NullPointerException. Am I misunderstanding the above quote from the JLS? If yes, could someone explain more the meaning of the above quote or give an example where it would occur?