使用NullPointerException测试null是不好的风格?

我有以下模式的一些代码:

return a().b().c().d().e(); 

现在因为这些方法中的每一个都可以返回null ,所以通常会测试这个:

 if( (a()!=null) && (a().b() != null) && ....) { return a().b().c().d().e(); } else { return null; } 

(也许可以使用一些局部变量来避免重复调用)

我很想做:

 try { return a().b().c().d().e(); } catch (NullPointerException e) { return null; } 

这被认为是不好的风格? 效率低下? 还是挺好的?

不要这样做。 与基本空检查相比,抛出和捕获exception相当昂贵。

您可能也有兴趣知道已经为将来的Java版本提出了语法,这将使这更简单。 它会是这样的:

 a()?.b()?.c()?.d() 

“?” 操作将是“。”的可选版本。 运营商。 如果LHS为null,则在该点返回null,而不是尝试评估RHS。 正是你在寻找什么,但我担心它没有为Java 7做好准备。不知道Java 8的这个function的状态。

它被认为是不好的风格,因为exception应该代表exception条件,在正常执行期间不可能出现的事情以及表明出现问题的事情。 使用exception检查对象是否为null使用此机制来检查更平凡的故障。 正如Konstantin的post所提到的,使用exception也会产生运行时间损失。 此外,将所有错误包装在一个NullPointerException意味着您将丢失有关特别是出错的信息。 哪个函数返回null ? 这是由于正常错误,还是有更严重的事情发生?

您还没有考虑其他选项。 而不是让a()b(),等返回null来表示错误,考虑让它们抛出更详细的exception,解释为什么它们不能返回某些东西。 如果由于网络连接丢失而导致它们失败,请让它们抛出IOException或类似的东西。 如果因为你的数组索引不正确而失败,那么也要清楚。

简而言之,如果您想使用exception,请使用它们来更精确地通知程序的其余部分发生了什么。 这样,您可以采取更细粒度的纠正措施。

通常,这行代码本身就很糟糕,忽略了null问题。 参见“德米特定律”或“最少知识原理” 。

 return a().b().c().d().e(); 

如果我无法控制a,b,c,d和e,我会重写以下内容。

 if( (a()!=null) && (a().b() != null) && ....) { return a().b().c().d().e(); } else { return null; } 

因为这仍然是令人发指的,但是当某些东西混乱并且我需要读取堆栈跟踪时更有用。

 B b = aa(); if(b == null) { return null; } C c = bb(); if(c == null) { return null; } D d = cc(); if(d == null) { return null; } return dd(); 

不,捕获NullPointerException不是一件合适的事情。 这有点像在try块中包装for循环来捕获ArrayIndexOutOfBoundsException

如果这应该是一个流畅的API ,其中链接是一个强度和目标,那么它永远不应该返回空值。

我不这样做主要是因为如果a()b()c()等有一个导致它们抛出NullPointerException的错误? 在那种情况下,你抓住它并继续前进,而不应该。

更改方法,以便它们不返回null或避免链接可返回null的方法。

而不是返回null ,让每个返回NullObject或其他东西。 阅读Null对象模式 。