- 先來看一下JDK1.6的API:
NullPointerException (Java Platform SE 6) public class NullPointerException extends RuntimeExceptionnull
當應用程序試圖在需要對象的地方使用時,拋出該異常。這種情況包括:
* 調用 null 對象的實例方法。 * 訪問或修改 null 對象的字段。 * 將 null 作為一個數組,獲得其長度。 * 將 null 作為一個數組,訪問或修改其時間片。 * 將 null 作為 Throwable 值拋出。
應用程序應該拋出該類的實例,指示其他對 null 對象的非法使用。
由以上說明可以看出,最主要的原因就是調用的對象是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,不會報異常。
- 使用Java語言開發應用程序不管是J2SE還是J2EE的,沒有幾個開發者沒經歷空指針異常 (NullPointerException)錯誤的,作為一個runtime Exception最為常見的幾種原因是:
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 方法