Почему этот поиск карты производит NPE? - PullRequest
4 голосов
/ 28 сентября 2010

Рассмотрим этот класс:

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 Ответ

17 голосов
/ 28 сентября 2010

Значение для клавиши "B" равно нулю. Но тип возвращаемого значения вашего условного выражения - float (примитив), потому что вы используете литерал 0F, а не Float (обертка), поэтому значение должно быть автоматически помещено (в примитив) и затем автоматически помещено (обратно в объект). Это приводит к 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 определяет тип возврата условного оператора. Это довольно сложно, и мне легче учиться с помощью экспериментов: -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...