問題
為了避免空指標呼叫,我們經常會看到這樣的陳述句
...
if (someobject != null) {
someobject.doCalc();
}
...
最終,專案中會存在大量判空代碼,多么丑陋繁冗!如何避免這種情況?我們是否濫用了判空呢?
精華回答
這是初、中級程式猿經常會遇到的問題,他們總喜歡在方法中回傳null,因此,在呼叫這些方法時,也不得不去判空,另外,也許受此習慣影響,他們總潛意識地認為,所有的回傳都是不可信任的,為了保護自己程式,就加了大量的判空,
吐槽完畢,回到這個題目本身,進行判空前,請區分以下兩種情況:
1、null 是一個有效有意義的回傳值(Where null is a valid response in terms of the contract; and)
2、null是無效有誤的(Where it isn't a valid response.)
你可能還不明白這兩句話的意思,不急,繼續往下看,接下來將詳細討論這兩種情況
先說第2種情況
null就是一個不合理的引數,就應該明確地中斷程式,往外拋錯誤,這種情況常見于api方法,例如你開發了一個介面,id是一個必選的引數,如果呼叫方沒傳這個引數給你,當然不行,你要感知到這個情況,告訴呼叫方“嘿,哥們,你傳個null給我做甚",
相對于判空陳述句,更好的檢查方式有兩個
(1)assert陳述句,你可以把錯誤原因放到assert的引數中,這樣不僅能保護你的程式不往下走,而且還能把錯誤原因回傳給呼叫方,豈不是一舉兩得,(原文介紹了assert的使用,這里省略)
(2)也可以直接拋出空指標例外,上面說了,此時null是個不合理的引數,有問題就是有問題,就應該大大方方往外拋,
第1種情況會更復雜一些
這種情況下,null是個”看上去“合理的值,例如,我查詢資料庫,某個查詢條件下,就是沒有對應值,此時null算是表達了“空”的概念,這里給一些實踐建議:
1、假如方法的回傳型別是collections,當回傳結果是空時,你可以回傳一個空的collections(empty list),而不要回傳null,這樣呼叫側就能大膽地處理這個回傳,例如呼叫側拿到回傳后,可以直接print list.size(),又無需擔心空指標問題,
(什么?想呼叫這個方法時,不記得之前實作該方法有沒按照這個原則?所以說,代碼習慣很重要!如果你養成習慣,都是這樣寫代碼(回傳空collections而不回傳null),你呼叫自己寫的方法時,就能大膽地忽略判空)
2、回傳型別不是collections,又怎么辦呢?
那就回傳一個空物件(而非null物件),下面舉個“栗子”,假設有如下代碼
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
其中,Parse有一個介面FindAction,這個介面會依據用戶的輸入,找到并執行對應的動作,假如用戶輸入不對,可能就找不到對應的動作(Action),因此findAction就會回傳null,接下來action呼叫doSomething方法時,就會出現空指標,
解決這個問題的一個方式,就是使用Null Object pattern(空物件模式)
我們來改造一下類定義.如下,這樣定義findAction方法后,確保無論用戶輸入什么,都不會回傳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;
}
}}
對比下面兩份呼叫實體
1、冗余:每獲取一個物件,就判一次空
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();
}
2、精簡
ParserFactory.getParser().findAction(someInput).doSomething();
因為無論什么情況,都不會回傳空物件,因此通過findAction拿到action后,可以放心地呼叫action的方法,
其他回答精選
如果要用equal方法,請用object<不可能為空>.equal(object<可能為空>))例如
"bar".equals(foo)
而不是用
foo.equals("bar")

另外如果你想更好的提升你的編程能力,學好C語言C++編程!彎道超車,快人一步!筆者這里或許可以幫到你~
分享(原始碼、專案實戰視頻、專案筆記,基礎入門教程)
歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
編程學習:

編程學習:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/271858.html
標籤:其他
