Java 为什么地图检索会产生NPE?

Java 为什么地图检索会产生NPE?,java,nullpointerexception,Java,Nullpointerexception,以这一类为例: 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"};

以这一类为例:

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);
        }       
    }
}
如果我将现有行替换为紧靠其下方的注释行,它将按预期工作,分配foo=null。为什么这两种情况下的行为不同?

键“B”的值为空。但是条件表达式的返回类型是float(原语),因为您使用的是literal
0F
,而不是float(包装器),因此该值必须自动取消绑定(到原语),然后自动装箱(返回到对象)。这导致了NPE

与使用时发生的情况进行比较

Float foo = (tm == null ? Float.valueOf(0f) : tm.get(key));
作为补充说明,以下是您的条件正在执行的操作(显示显式装箱):


定义条件运算符的返回类型。它相当复杂,我发现通过实验更容易学习:-)。

这很棘手-没想到条件会根据第一个改变第二个子句的返回类型。。。谢谢你的解释。@Greg:是的,那部分一开始可能会让人困惑。Java需要静态地(在编译时)知道返回类型是什么,因此它需要选择一个对这两种可能性都有效的返回类型。
Float foo = (tm == null ? Float.valueOf(0f) : tm.get(key));
Float foo;
float conditionalResult;

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