Why does this map search give NPE?

Consider this class:

public class TestMap extends HashMap<String, Float> { public static void main(String[] args) { TestMap tm = new TestMap(); tm.put("A", 0F); tm.put("B", null); String[] keys = new String[]{"A", "B"}; for (String key : keys) { System.out.println(key); Float foo = (tm == null ? 0F : tm.get(key)); // Float foo = tm.get(key); System.out.println(foo); } } } 

A NullPointerException is thrown on the Float foo =... line Float foo =... during the second iteration of the loop:

 A 0.0 B Exception in thread "main" java.lang.NullPointerException at TestMap.main(TestMap.java:14) 

If I replace the existing line with the commented line immediately below, it will work as expected, assigning foo = null. Why is the behavior different in these two cases?

+4
source share
1 answer

The value for key "B" is null. But the return type of your conditional expression is float (primitive) because you use the literal 0F , not float (wrapper), so the value should be autounboxed (for the primitive) and then autoboxed (back to the object). This leads to NPE.

Compare with what happens when using

 Float foo = (tm == null ? Float.valueOf(0f) : tm.get(key)); 

As an additional explanation, here is what your conditional does (showing explicit boxing):

 Float foo; float conditionalResult; if ( tm == null ) { conditionalResult = 0F; } else { conditionalResult = tm.get(key).floatValue(); //this throws the NPE } foo = Float.valueOf(conditionalResult); 

JLS 15.25 determines what the return type of the conditional statement will be. This is quite complicated, and it’s easier for me to learn from experiments :-).

+17
source

All Articles