2010-09-28 2 views
4

Рассмотрим этот класс:Почему этот поиск карт дает NPE?

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

NullPointerException производится на линии Float foo =... во второй итерации цикла:

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

Если я заменить существующую линию с комментировал линии непосредственно под ним, работает как и ожидалось, присваивая foo = null. Почему поведение по-разному в этих двух случаях?

+1

Я бы объявил «final TestMap tm = ...» и отказался от проверки 'tm == null'. –

ответ

17

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

+0

Это сложно - не ожидал условного изменения типа возврата второго предложения на основе первого ... спасибо за объяснение. – Greg

+0

@Greg: Да, эта часть может сбивать с толку вначале. Java должен знать статически (во время компиляции), что такое тип возврата, поэтому ему нужно выбрать один тип возврата, который работает для обеих возможностей. –

Смежные вопросы