欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何避免非空判断

程序员文章站 2024-03-15 08:22:17
...

    刚开始编程时,我们经常面对这样的情况,我们不知道也不相信我们的方法协议,所以过多的进行非空检查。而且,我们经常返回null,导致调用者要进行非空检查。

    有两种情况会出现非空检查:

    1. null是个合法的返回值,对于我们定义的方法协议而言;

    2. null不知一个合法的返回值。

    情况(2)很简单。我们可以使用assert语句,或者允许方法失败(比如,空指针异常)。断言是一个经常使用的Java特性,在1.4版本添加的。它的语法如下:

asset <condition>

    或者

assert <condition> : <object>

    <condition>是一个布尔表达式,<object>的toString()方法的返回值就是错误信息。

    如果<conditoin>不成立,assert语句会抛出一个Error(AssetionError)。默认情况下,Java会忽略这些断言。你可以通过传递-ea参数给JVM来启用断言。你甚至可以为单独的package或者class启用和禁用断言。也就是说,你可以在开发和测试环境下启用断言,而在生产环境下禁用断言。

    这种情况下,不用断言也可以,因为程序一样会失败。唯一的区别是,使用断言会让程序更早的、在更合理的场合失败,同时会提示有意义的信息。

    情况(1)有点复杂。如果你不能控制你所调用方法的返回值,那就有点麻烦了。如果null是一个合法的返回值,你就必须去检查它。

    如果你能控制你调用的方法,情况就不一样了。避免使用null作为返回值。如果方法的返回值是一个Collection,返回EmptyCollection而不返回null是一个明智的选择。

    如果返回值不是集合,就又有点难办了。考虑下面的情况,如果你有这样的接口:   

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

   Parser接受用户的输入并进行解析,比如实现一个命令行的接口。现在你会允许这个方法返回null,如果没有合法的Action。这就会导致我们说的非空检查。

    一个选择是不返回null,而是使用Null Object Pattern

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;
    }
  }
}

   

    对比

Parser parser = ParserFactory.getParser();if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response}Action action = parser.findAction(someInput);if (action == null) {
  // do nothing} else {
  action.doSomething();}

    和

arserFactory.getParser().findAction(someInput).doSomething();

    后者是一个更好的写法,因为代码更简洁。

    也就是说,由findAction()方法抛出一个异常,这个异常含有有意义的信息,这种方式更恰当。它比调用函数抛出一个NullPoninterExceptiong更友好。

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

    如果你觉得try/catch语句不够简洁,可以构造一个给用户反馈的Action。

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}

转载于:https://my.oschina.net/kisscoder/blog/667282