当我第一次从c转到Java时,我认为我已经完成了所有烦人的参数检查,在每个函数的开头。 (有福的例外)
最近我意识到我正在慢慢地再次回到那种做法,我开始对所有的
感到非常生气if (null == a || null == b || null == a.getValue() || ...)
{
return null;
}
例如,我有一个实用工具类,用于分析网页并从中提取特定元素。用null元素调用dom对象函数通常会导致异常 - 所以在我在这个类中编写的几乎所有函数中都有无数的null检查:
private URL extractUrl(Element element) throws Exception {
if (null == element) {
return null;
} ...
public List<Object> getConcreteElements(String xpath) throws Exception {
if (null == xpath) {
return Collections.emptyList();
}...
public String getElementsAsXML(String xpath) throws Exception {
if (null == xpath) {
return null;
}...
在每个功能的开头。这是我应该习惯的东西,还是有一些我不知道的编码习惯可以简化我的生活?
答案 0 :(得分:7)
返回null意味着调用者必须始终检查方法的结果。意思是更悲惨的空检查。
请考虑使用NullObject模式,返回有效对象但具有空操作。即如果返回集合或类似的空列表。
答案 1 :(得分:4)
在组件的公共边界,您总是必须进行数据验证。
对于内部方法,assert
传递的值是正确的更好。
如果可以的话,返回null是最好避免的。要么失败那么在那里表示你上游有一个错误(内部情况)或者如果有这样的东西可以返回一个空的或默认的对象(公共情况)。
答案 2 :(得分:2)
是的,他们真的很讨厌。我发现一些小事情至少可以减少这个:
一些习语最小化空检查 - 例如
if(string!= null&amp;&amp; string.equals(“A”) - &gt; if(“A”.equals(string))
但总的来说,你是对的。如果我的代码没有空检查和记录语句,那么根本就没有任何东西;)
答案 3 :(得分:1)
如果对您的应用程序有意义,则只检查null-return-null。可能是返回null只会导致客户端代码出现问题,而客户端代码不会出现空值。可能是因为输入错误而没有合理的返回值,在这种情况下使用例外。
至于你是否应该检查参数,这取决于谁在使用该功能。如果它是私人功能,检查可能有点过分。如果它是一个公共API函数,你绝对应该检查。
答案 4 :(得分:1)
根据我的经验,如果任何API的默认“合同”是null
参数值且不允许null
结果,则Java应用程序更易于维护。如果方法设计为允许null
参数或返回null
,则应在Javadoc中明确指定含义和环境。
如果传递了null
,而API没有明确允许这样做,那么这是一个错误,最好的办法是使用NPE快速失败。 (国际海事组织,没有必要记录NPE的可能性......可以假设。)如果null
不是一个有意义的(记录的)参数值,那么测试null
和返回null
仅用于传播错误数据并使调试代码变得更加困难。如果你的方法使用提供的null
参数并导致NPE,那就这样吧。如果不使用参数但它保存了值以供将来使用,那么值得测试null并显式抛出NPE。
我还尝试避免使用null
来表示空列表或空数组的(通常是错误的)优化,至少在API级别。
现在有些情况下API设计使用null
s是有意义的;例如在API中,对象参数实现某种插件行为/策略,或者在未提供可选方法参数时使用null
。但你需要考虑并记录它。
答案 5 :(得分:1)
如果您检查非法值,请不要犹豫,抛出IllegalArgumentExceptions以通知调用者他犯了错误。您可以隐藏私有方法中的边界/非法值检查,这样可以提高代码的可读性,例如 - 只需要一个示例:
private URL extractUrl(Element element) throws Exception {
validateExactUrlParameter(element);
// the real url extraction code
}
private static validateExactUrlParameter(Element element)
throws IllegalArgumentException {
if (null == element) {
throw new IllegalArgumentException("Null value not allowed for exactUrl method");
}
// do some more checks here, if required
}
如果你想避免try / catch块,那么考虑抛出未经检查的异常(RuntimeException或自定义子类)。