2010-09-28 53 views
4

考慮這個類:爲什麼這個地圖檢索產生一個NPE?

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

如果我用註釋行替換現有的線緊貼它下面的工作:

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 =...生產如預期的那樣,分配foo = null。爲什麼這兩種情況下的行爲不同?

+1

我會聲明'final TestMap tm = ...'並放棄'tm == null'檢查。 – 2010-09-28 16:12:10

回答

17

鍵「B」的值爲空。但是由於你使用文字0F而不是Float(包裝器),所以你的條件表達式的返回類型是float(原始),所以這個值必須被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 2010-09-28 16:07:16

+0

@Greg:是的,這部分起初可能會讓人困惑。 Java需要靜態地(在編譯時)知道返回類型是什麼,所以它需要選擇適用於這兩種可能性的單一返回類型。 – 2010-09-28 16:10:28

相關問題