Code Smell : Null : 空值

Null表示什么?

我们的代码用Null表示了太多的事情:

  • 有意或无意导致的从未初始化的值
  • 无效值/不需要的值
  • 值不存在(比如从数据库中查找不到)
  • 可能出现了严重的错误导致本该存在的值没有了
  • 其他各种情况

由于上述种种,NPE总是时不时出现在我们的程序中.NPE导致的BUG也数不胜数,没见过NPE的程序员估计还没出生.

Null是个尤其难解决的问题,主要原因是开发人员很难明确的知道Null表达的实际意义.从字面上看Null表示没有任何含义的值.但用它来表达上面的任何情况都不足够清楚.

症状

当Null在你的程序里面成为顽疾,往往会有如下症状.

  • 随处可见的Null检查if(xx != null).

    这种情况说明开发人员不清楚传递的变量为null的意义,只能无奈的做防御式Null检查.

    开发人员永远不知道返回值是否可能为null,也永远无法保证在所有地方都使用的Null检查.

  • 方法直接使用return null

可能的解决方案

  • Java8+或guava的Optional,它虽然不是处理一切Null问题的银弹,但是当一个public方法通过明确返回null来表示效果不存在时,使用Optional是更好的方案.
  • @NotNull/@Nullable在Intellij,guava,lombok,jsr305中都提供了这样的注解,Intellij IDEA对这些注解的提供了编码时检查.在IDE里面查看一个方法,将@NotNull临时添加在参数前,IDE会告知你该参数是否有被传递null值,如果没有,那么你可以去掉该注解,然后在Javadoc中加入参数不能为null的说明.当然如果你愿意保留@NotNull注解,可以更显著地提醒代码的维护人员,但是需要引入一个注解依赖.
  • 在异常处理中返回null是非常不友好的,调用者往往不希望收到null值,进而导致NPE.整个过程缺少对错误信息的描述.应当改为抛出一个具有描述信息的异常,这对发现错误和分析问题更有价值.

总结

如果方法可能返回null,那么考虑改为返回Optional.

方法的参数通过@NotNull/@Nullable来告知调用者是否允许传递null值,同时为IDE的静态代码分析提供帮助.

异常处理中永远不要返回null值,改为抛出具有描述信息的异常.