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

时间:2010-09-28 15:50:38

标签: 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"};

        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);
        }       
    }
}

在循环的第二次迭代期间,在行Float foo =...上生成NullPointerException:

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

如果我用下面的注释行替换现有行,它会按预期工作,指定foo = null。为什么这两种情况的行为不同?

1 个答案:

答案 0 :(得分:17)

键“B”的值为null。但是由于您使用文字0F而不是Float(包装器),因此条件表达式的返回类型是float(primitive),因此值必须自动装箱(到原语)然后自动装箱(返回)到一个对象)。这导致了NPE。

与使用

时发生的情况相比较
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);

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