NullPointerException instead of null (JVM Bug?)

I found strange behavior in the current version of Java 8. In my opinion, the following code should be good, but the JVM throws a NullPointerException :

 Supplier<Object> s = () -> false ? false : false ? false : null; s.get(); // expected: null, actual: NullPointerException 

It doesn't matter which lambda expression it is (the same with java.util.function.Function ) or which generic types are used. Instead of false ? : false ? : There may also be more meaningful expressions. The example above is very short. Here is a brighter example:

 Function<String, Boolean> f = s -> s.equals("0") ? false : s.equals("1") ? true : null; f.apply("0"); // false f.apply("1"); // true f.apply("2"); // expected: null, actual: NullPointerException 

However, these parts of the code work fine:

 Supplier<Object> s = () -> null; s.get(); // null 

and

 Supplier<Object> s = () -> false ? false : null; s.get(); // null 

Or with the function:

 Function<String, Boolean> f = s -> { if (s.equals("0")) return false; else if (s.equals("1")) return true; else return null; }; f.apply("0"); // false f.apply("1"); // true f.apply("2"); // null 

I tested two versions of Java:

~# java -version

openjdk version "1.8.0_66-internal" OpenJDK runtime (build 1.8.0_66-internal-b01) OpenJDK 64-bit server VM (build 25.66-b01, mixed mode)

C:\>java -version

java version "1.8.0_51" Java (TM) SE Runtime Environment (build 1.8.0_51-b16) Java HotSpot (TM) 64-bit server VM (build 25.51-b03, mixed mode)

+7
java ternary-operator lambda jvm
source share
1 answer

This has nothing to do with lambda expressions; just the return type of the ternary operator in this case is boolean , so automatic unpacking will be used.

NPE also rushes here:

 public class Main { private static Object method() { return false ? false : false ? false : null; } public static void main(String[] args) { System.out.println(method()); } } 

So what exactly is going on here?

Firstly, the expression "embedded" ( false ? false : null ) is evaluated according to JLS ยง15.25 :

The conditional operator is syntactically right-associative (it groups right to left). So a? B: c? D: e? F: g means the same as a b :? (? CD: (E: g)).

The type of the built-in expression is boolean (in the boolean box), so it can include both false and null .

Then the whole expression:

 false ? false : (Boolean expression) 

Then again in accordance with JLS ยง15.25 :

If one of the second and third operands has a primitive type T and the type of the other is the result of applying the box transformation (Section 5.1.7) to T, then the conditional expression type is T.

So, the first argument has a primitive type boolean ( T in the specification), the type of the other is boxed T ( boolean ), so the type of the whole expression is boolean .

Then, at run time, the inline expression evaluates to null , which is automatically unpacked to boolean , causing NPE.

+7
source share

All Articles