原问题:
有没有好的选择可以避免掉这段代码?
更新:潘(Pan,人名),我也不是太清楚自己的问题。我想强调的是,如果你想要访问某个对象的字段或方法,对这个对象是否为null的测试是必要的。例如:
...
if (someobject != null) {
someobject.doCalc();
}
...
在这种情况下,我不必知道对象是否为null,就可以避免空指针(NullPointerException)的错误。但因此,我的代码里就会满是这种测试。
不过还是非常感谢你的回答,我又得到了一些新的见解。
- 空值是符合条件的有效响应;和
- 不是有效响应
第2种情况简单。要么用assert语句(断言)要么允许抛错(例如,NullPointerException空指针错误)Assertions是java1.4以后新增的一个没有被高度利用的java特性。语法如下:
表达式1:assert *<condition>*
或者
表达式2:assert *<condition>* : *<object>*
<object>的toString()输出将会被包含在错误(error)中。
如果<condition>条件返回非真,一条assert语句将抛出一个错误(AssertionError) (注:<condition>表示一个boolean表达式)。默认情况下,Java是忽略Assertions的。你可以通过功能参数 -ea 开启assertions功能。你可以开启(关闭)某些类或包的assertion功能。这就意味着,在开发和测试时,你可以通过assertions功能来验证代码,并且在生产环境中禁用他们,虽然我的测试表明aseertions没有对性能的影响。(这句也翻译残了,~~~~(>_<)~~~~ )
在这种情况下不适用断言也是可以的:代码最终会运行出错。唯一的区别是,断言可能发生的更早些,通过更有意义的方式并且可能伴随着附加的信息,如果你没有预料到这种错误,这可以帮助你找出为什么错误会发生。
第一种情况稍微困难些。如果你在调用的时候,对代码没有控制,那你就完蛋了。如果null是有效的响应,你必须要检查它。
如果你确实对代码做了控制,那么(这是通常的情况),这就是另一回事儿了。避免用null作为响应。几乎不管什么时候,用返回集合的方法,很容易:返回空集(或者空数组)而不是返回nulls。
对于非空集合可能就要难一些。设想这样一个例子:如果你有这些接口
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
其中 Parser (解析器)接受原始用户的输入并找些事做,或许是你正在为某些东西实现一个命令行界面的时候。现在你可能会约定如果没有适当的操作那么就返回null。这就导致了你谈到的为空检查。
另一种解决方法是决不返回null,而是使用Null Object模式:
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) {
// 现在怎么办?
// 这里可能是一个null不是(或不应该是)有效响应的例子
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
}
设计2
ParserFactory.getParser().findAction(someInput).doSomething();
对比设计1和设计2,后者是一个更好一些的设计,它使得代码更加简洁。