Consider this sample code:
public static void main(String[] args){
SomeObj obj = null;
if (obj == null || obj.getSomeMethod() == null) {
System.out.println("Obj is null");
}
if (result((x, y) -> x == null || y == null, obj, obj.getSomeMethod())) {
System.out.println("Obj is null");
}
}
private static <X, Y> boolean result(final BiPredicate<X, Y> p, final X argX, final Y argY){
return p.test(argX, argY);
}
In the first If condition I get the message "obj is null" but in the second If condition I get a NullPointerException. This BiPredicate should't be a short circuit operator (if the first condition is true don't bother evaluating the second one)?
CodePudding user response:
No, you're passing three arguments to result
:
- The
BiPredicate
X
Y
They get evaluated before calling result
, which means the BiPredicate
is evaluated and returns a BiPredicate
(which is not executed), then X
is evaluated, than Y
but Y
is obj.getSomeMethod()
and obj
is null, so the NullPointerException
is thrown.
CodePudding user response:
This actually has nothing to do with BiPredicate
per se.
if (result((x, y) -> x == null || y == null, obj, obj.getSomeMethod())) {
is just invoking a method, in exactly the same way that
if (someMethod("Hello", obj, obj.getSomeMethod())) {
does: Java evaluates all of the arguments, and then passes them to the method.
So, it evaluates obj.someMethod()
, whether or not obj
is null
. If it is null
, you will get a NullPointerException
here.
BiPredicate
has no special support in the language: it's just a regular library-defined interface. You don't get any special lazy evaluation by using it.