Java中如何避免空指針異常
這對于我來說是一個很合理常見的問題,由初級過度到中級程序員的時候經(jīng)常會遇到。他們不知道也不信任正在用的約定,并且小心的檢查著null。還有當(dāng)他們寫代碼的時候,總是會依賴于通過返回空(NULL)來表明某些意義,因此需要調(diào)用者去檢查Null。
換種方式來說,有兩種情景空指針的檢查會出現(xiàn):
就約定來說是一個合理的響應(yīng)
不是合理的響應(yīng)
第二種很簡單,可以通過用assert或者直接允許失敗,例如NullPointerException。Assertions是一個從Java1.4加進來的高度未被利用的特性,語法是:
- assert <condition>
 
或者
- assert <condition> : <object>
 
condition是一個布爾表達(dá)式,object是一個對象(其toString()方法的輸出將會被包含在錯誤里)。
如果condition為false的話,assert將會拋出一個Error(AssertionError).
默認(rèn)Java會忽略斷言你可以通過在JVM中傳入一個-ea參數(shù)來啟用斷言,
你可以為單獨的一個包或者類啟動關(guān)閉assertions。這意味著你可以在開發(fā)和測試的時候通過斷言來驗證代碼,
在發(fā)布產(chǎn)品的時候關(guān)閉它,盡管我下面展示的測試中并沒有因為assertions而損失性能。
在這個代碼段中不用斷言也可以,因為他會運行失敗的,就像加了斷言一樣。唯一的區(qū)別是
有了斷言可能會發(fā)生的更快一些,更有意義,并且會附加一些額外的信息,而這可以幫助你弄明白
失敗的原因。
***種有一點棘手。如果你對不能控制正在調(diào)用的這段代碼,那你就卡住了。
如果Null是一個合理的返回值,你就應(yīng)該檢查它。
如果是你能夠控制的代碼,那就是個完全不同的故事情景了.盡量避免用NULL作為返回值。
對于返回Collections的集合很容易,返回Empty(一個空集合或者數(shù)組),而不是一直用null作為返回值。
對于不是返回Collections的方法會有一點復(fù)雜??紤]下面這個例子:
- public interface Action {
 - void doSomething();
 - }
 - public interface Parser {
 - Action findAction(String userInput);
 - }
 
Parser采用用戶的輸入作為參數(shù),然后做一些事情(例如模擬一個命令行)?,F(xiàn)在你可能會
返回null,如果沒找到對應(yīng)輸入的動作的話,這就導(dǎo)致了剛才說過的空指針檢查。
一個可選的解決方案是永遠(yuǎn)不要返回null,而是返回一個空對象,
- public class MyParser implements Parser {
 - private static Action DO_NOTHING = new Action() {
 - public void doSomething() { /* do nothing */ }
 - };
 - public Action findAction(String userInput) {
 - // ...
 - if ( /* we can't find any actions */ ) {
 - return DO_NOTHING;
 - }
 - }
 - }
 
比較這段代碼:
- Parser parser = ParserFactory.getParser();
 - if (parser == null) {
 - // now what?
 - // this would be an example of where null isn't (or shouldn't be) a valid response
 - }
 - Action action = parser.findAction(someInput);
 - if (action == null) {
 - // do nothing
 - } else {
 - action.doSomething();
 - }
 
和這段:
- ParserFactory.getParser().findAction(someInput).doSomething();
 
這是個更好的設(shè)計,因為足夠簡潔,避免了多余的判斷。即便如此,或許比較合適的設(shè)計是:findAction()方法之惡杰拋出一個異常,其中包含一些有意義的錯誤信息-----特別是在這個案例中你依賴于用戶的輸入。讓findAction()方法拋出一個異常而不是簡單的產(chǎn)生一個沒有任何解釋的NullPointerException 要好得多。
- try {
 - ParserFactory.getParser().findAction(someInput).doSomething();
 - } catch(ActionNotFoundException anfe) {
 - userConsole.err(anfe.getMessage());
 - }
 
或者你認(rèn)為try/catch 的機制太丑了,你的action應(yīng)該跟用戶提供一個反饋而不是什么都不做:
- public Action findAction(final String userInput) {
 - /* Code to return requested Action if found */
 - return new Action() {
 - public void doSomething() {
 - userConsole.err("Action not found: " + userInput);
 - }
 - }
 - }
 
















 
 
 







 
 
 
 