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?
There are four kinds of method references: Static methods. Instance methods of particular objects. Instance methods of an arbitrary object of a particular type.
I prefer method references for multiple-argument lambdas, and sometimes to emphasize that the lambda is only about a single method call. There is less to go wrong with a method reference: you might misspell the argument at use site, accidentally referring to a variable from outer scope, etc.
Lambda expression is an anonymous method (method without a name) that has used to provide the inline implementation of a method defined by the functional interface while a method reference is similar to a lambda expression that refers a method without executing it.
Oh darn! That's an eclipse bug (ECJ
), it fails with javac/java
(I've tried 9 here in the example, but same thing happens in 8):
Testing...
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:221)
at org.eugene.so.DeleteMe.main(DeleteMe.java:11)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With