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

Car*_*ten 9 java coding-style nullpointerexception

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

return a().b().c().d().e();
Run Code Online (Sandbox Code Playgroud)

现在因为每个方法都可以返回null,人们通常会测试这个:

if( (a()!=null) && (a().b() != null) && ....) {
   return a().b().c().d().e();
} else  {
  return null;
}
Run Code Online (Sandbox Code Playgroud)

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

我很想做:

try {
   return a().b().c().d().e();
} catch (NullPointerException e) {
   return null;
}
Run Code Online (Sandbox Code Playgroud)

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

Kon*_*hik 16

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

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

a()?.b()?.c()?.d()
Run Code Online (Sandbox Code Playgroud)

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


tem*_*def 5

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

您还没有考虑其他选项.而不是a(),b(),等返回null到发出错误信号,考虑让它们投入更多的详细的解释例外,为什么他们不能返回的东西.如果因为网络连接丢失而导致它们失败,请让它们抛出IOException或类似的东西.如果它们因为你的数组索引错误而失败,那么也要清楚.

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


Jon*_*ust 5

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

return a().b().c().d().e();
Run Code Online (Sandbox Code Playgroud)

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

if( (a()!=null) && (a().b() != null) && ....) {
   return a().b().c().d().e();
} else  {
  return null;
}
Run Code Online (Sandbox Code Playgroud)

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

B b = a.a();
if(b == null)
{
   return null;
}

C c = b.b();
if(c == null)
{
   return null;
}

D d = c.c();
if(d == null)
{
   return null;
}

return d.d();
Run Code Online (Sandbox Code Playgroud)

不,捕捉NullPointerException不适合做.这有点像for在一个try块中包裹一个循环来捕获ArrayIndexOutOfBoundsException.

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