- 先來看一下JDK1.6的API:
NullPointerException (Java Platform SE 6) public class NullPointerException extends RuntimeExceptionnull
當應用程序試圖在須要對象的地方使用時,拋出該異常。這種狀況包括:html
* 調用 null 對象的實例方法。 * 訪問或修改 null 對象的字段。 * 將 null 做爲一個數組,得到其長度。 * 將 null 做爲一個數組,訪問或修改其時間片。 * 將 null 做爲 Throwable 值拋出。
應用程序應該拋出該類的實例,指示其餘對 null 對象的非法使用。java
由以上說明能夠看出,最主要的緣由就是調用的對象是NULL數組
- 常常會出現空指針的狀況有:
(1)字符比較 String str1 = someclass.getSomeString(); if(str1.equalsIgnoreCase("YES")) { //do something } else if(str1.equalsIgnoreCase("NO")) { //do something else } (2)讀取配置文件 props.getProperty("somekey"); (3)從MAP取值 map.get("key"); (4)從Session取值 String userName = request.getSession().getAttribute("userName");
等等,這裏發生NullPointerException的機會很是大,並且運行狀況每每和用戶輸入的數據有關,因此不容易被發現. 如何避免空指針異常?最主要的是養成一個好的編碼習慣,在對對象進行調用方法、比較等等操做時,要判斷一下對象有沒有可能會是NULL,提早進行處理。多線程
str1.equalsIgnoreCase("YES"); 而應該寫成這樣:
"YES".equalsIgnoreCase(str1), 這樣就能夠避免空指針異常。
這兩種寫法的差別,主要是程序對對象的操做是先判斷再執行,就是先判斷對象是否存在,而後再去執行其它操做。第一種方式在判斷str1的時候,若是str1是null,這是程序確定會拋出異常,而第二種就OK,不會報異常。
1 1. 對象未初始化而直接引用對象值或者方法到的,代碼示例: 2 package com.fish.codesample; 3 public class JavaNullSample { 4 5 private String name; 6 public JavaNullSample() { 7 } 8 public String getName() { 9 return name; 10 } 11 public static void main(String[] args) { 12 new JavaNullSample().getName().length(); 13 } 14 } 15 2. 對象引用已經不存在或者被JDBC關閉 16 一個經典的例子是JDBC connection已經關閉,ResultSet對象仍然被使用中,這個時候NullPointerException就被拋出。 17 18 3. 違反某些Java容器的限制,讀寫Null 值 19 這個方面首推的就java.util.HashTable,它不接受Null 做爲Key或者Value,若是試圖用Null做爲Key去讀取HashTable將會獲得NullPointerException,代碼示例: 20 Hashtable<String,String> table = new Hashtable<String,String>(); 21 String tKey = null; 22 // the following codes always throw NullPointerException 23 tKey = table.get(null); 24 table.put(tKey, null); 25 當使用TreeMap/TreeSet的時候,必定確保全部對象的屬性的值不爲Null,不然在調用get/set方法時候會拋出NullPointerException, 代碼示例: 26 TreeMap<Person, String> tMap = new TreeMap<Person, String>(); 27 Person personer1 = new JavaTreeMap(). new Person(); 28 Person personer2 = new JavaTreeMap(). new Person(); 29 personer1.setName("fish"); 30 tMap.put(personer1, "person1"); 31 tMap.put(personer2, "person2"); // throw NullPointerException 32 33 34 還有幾種相對比較難的Java NullPointerException異常 35 1. java Swing/AWT NullPointerException 36 1) 最多見的錯誤時忘記初始化某個Swing組件,當調用JFrame.getContentPane().add()方法時致使NullPointerException 37 2) 當調用JFrame.pack()的時候拋出NullPointerException,最可能的一個緣由是JFrame的容器中的Swing組件可能被開發者本身重寫而致使不適用pack(). 38 3) Java JDK6與JDK4的Swing監聽機制已經有很大的不一樣,若是在初始化的時候觸發Listener致使執行listener的某些方極可能致使拋出NullPointerException 39 4) 某些Java2D/Java3D的組件可能致使NullPointerException 40 41 2. Socket鏈接丟失致使IO流的Java NullPointerException 42 43 3. 資源文件加載錯誤致使的NullPointerException,最多見的代碼示例以下: 44 InputStream in =this.getClass().getResourceAsStream(PropertiesName); 45 props.load(in); // throw NullPointerException if xml/property files missing 46 47 4. 多線程致使的NullPointerException 48 這種緣由致使的NullPointerException通常很難被發現,特別是在大型和複雜的系統中 49 並且一段時間內業很難被重現,修復這樣的bug成本很高,不修復這樣的bug代價很大,意味着用戶可能失去對該產品的信任。
[後記:Java NullPointerException作爲Java Runtime 異常,在開發中減小這樣錯誤的發生就是對代碼完成Junit的單元測試,對於一些重要的代碼要提升code review的次數從而提升代碼質量,增長產品的可靠性。]
單元測試
- 給嚮往遠方的你: 沒有比腳更長的路,沒有比人更高的山。 --汪國真《山高路遠》
如何避免null 值呢, JDK 1.8 中引入了Optional 方法測試
詳情連接this