我使用object != null
很多以避免 NullPointerException
.
這有很好的替代方法嗎?
例如:
if (someobject != null) {
someobject.doCalc();
}
這避免了NullPointerException
,當物件是否為null
時,它是未知的.
注意,接受的答案可能已經過時,更新的方法請參閱 https://stackoverflow.com/a/2386013/12943 。
我使用object != null
很多以避免 NullPointerException
.
這有很好的替代方法嗎?
例如:
if (someobject != null) {
someobject.doCalc();
}
這避免了NullPointerException
,當物件是否為null
時,它是未知的.
注意,接受的答案可能已經過時,更新的方法請參閱 https://stackoverflow.com/a/2386013/12943 。
對我來說,這聽起來是初級到中級開發人員在某個時候往往面臨的一個相當常見的問題:他們要麼不知道,要麼不信任他們正在參與的合同,並防禦性地檢查nulls.此外,在編寫自己的程式碼時,他們往往依賴返回nulls來表示需要呼叫者檢查nulls的東西.
換句話說,有兩個例項null檢查出現:
在合同方面,null是有效的答覆;以及
其中它不是有效的響應.
(2)很容易.要麼使用assert
語句(斷言),要麼允許失敗(例如, NullPointerException ).斷言是一個高度低估的Java功能,新增在1.4中.語法是:
assert <condition>
要麼
assert <condition> : <object>
其中<condition>
是一個布林表示式,<object>
是一個物件,其toString()
方法的輸出將包含在錯誤中.
如果條件不是真的,assert
語句丟擲Error
(AssertionError
).預設情況下,Java忽略斷言.您可以透過將選項-ea
傳遞給JVM來啟用斷言.您可以啟用並禁用單個類和包的斷言.這意味著您可以在開發和測試時使用斷言驗證程式碼,並在生產環境中禁用它們,儘管我的測試顯示下一步沒有斷言的效能影響.
在這種情況下不使用斷言是可以的,因為程式碼只會失敗,這是如果使用斷言會發生的事情.唯一的區別是,對斷言,它可能會更快發生,更有意義的方式,並且可能帶有額外的資訊,這可能有助於您弄清楚如果您不期望它為什麼會發生這種情況.
(1)有點難.如果您對所呼叫的程式碼沒有控制權,那麼您就會被卡住.如果null是有效的響應,則必須檢查它.
但是,如果它是你控制的程式碼(通常情況是這樣),那麼它是一個不同的故事.避免使用nulls作為響應.使用返回集合的方法,很容易:返回空集合(或陣列)而不是nulls幾乎所有時間.
使用非集合可能更難.考慮這是一個例子:如果您有這些介面:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
其中Parser接受原始使用者輸入並找到需要做的事情,也許如果您正在為某些東西實現命令列介面.現在,如果沒有適當的操作,您可能會簽訂返回null的合同.這導致您正在討論的null檢查.
另一個解決方案是永遠不返回null,而是使用 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();
這是一個更好的設計,因為它會導致更簡潔的程式碼。
儘管如此,也許findAction()方法使用有意義的錯誤訊息丟擲異常是完全適當的 – 特別是在這種情況下,您依賴於使用者輸入.使用findAction方法丟擲異常比呼叫方法在沒有解釋的情況下打擊簡單的NullPointerException更好.
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
或者,如果您認為 try/catch 機制太醜,而不是 Do Noth 您的預設操作應該向使用者提供反饋。
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);
}
}
}