Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the reason behind null checks in method reference expression evaluation?

There are a bunch of questions where people have realized that creating a method reference with an expression that evaluates to a null value will result in a NullPointerException. As an example:

String s = null;
Supplier<char[]> fun = s::toCharArray;

This is due to the following paragraph in the java specification:

First, if the method reference expression begins with an ExpressionName or a Primary, this subexpression is evaluated. If the subexpression evaluates to null, a NullPointerException is raised, and the method reference expression completes abruptly. If the subexpression completes abruptly, the method reference expression completes abruptly for the same reason.

Now my question is, does anyone happen to know what the reason behind this (based on the many confused questions) counterintuitive specification was/is?

The only thing that comes to my mind is that in the following case it is hard to accurately report the error of the NullPointerException if it happens during the evaluation of the Supplier:

public static char[] callback(Supplier<char[]> supplier) {
    return supplier.get();
}

public static void main(String[] args) {
    String s = null;
    callback(s::toCharArray);
}
like image 414
Yanick Salzmann Avatar asked Dec 12 '18 13:12

Yanick Salzmann


2 Answers

The reason here is the fact that when you are creating non static method reference, it must have access to this. When you are trying to create reference to null object, there is no this anywhere, that is why it should fail on this step, instead of failing somewhere further in the code when it is used for the first time.

Imagine in one place you get the object, save it's method reference somewhere, and than use it in completely different part of code. You'll get an NPE not in the place where the error was made, but many lines of code away.

like image 166
maxpovver Avatar answered Oct 30 '22 17:10

maxpovver


Because the Java compiler is not a linter/logic checker.
Nothing in Java prevents you to trigger a NPE by dereferencing null.
For example Java doesn't prevent you from doing :

String s = null;
s.toString();

That is right before Java 8 and that is right still today for method references.

The paragraph you quote details simply how at runtime the JVM handles this point for method references that is that if a part of the method reference evaluation fails, the whole evaluation fails.

Note that in your actual example your IDE will probably emit a warning because the scope of the potential bug is very tight.

like image 26
davidxxx Avatar answered Oct 30 '22 17:10

davidxxx