问题

我使用object != null很多以避免 NullPointerException .

这有很好的替代方法吗?

例如:

 if (someobject != null) {
    someobject.doCalc();
}
 

这避免了NullPointerException,当对象是否为null时,它是未知的.

注意,接受的答案可能已经过时,更新的方法请参阅 https://stackoverflow.com/a/2386013/12943

  最佳答案

对我来说,这听起来是初级到中级开发人员在某个时候往往面临的一个相当常见的问题:他们要么不知道,要么不信任他们正在参与的合同,并防御性地检查nulls.此外,在编写自己的代码时,他们往往依赖返回nulls来表示需要调用者检查nulls的东西.

换句话说,有两个实例null检查出现:

  1. 在合同方面,null是有效的答复;以及

  2. 其中它不是有效的响应.

(2)很容易.要么使用assert语句(断言),要么允许失败(例如, NullPointerException ).断言是一个高度低估的Java功能,添加在1.4中.语法是:

 assert <condition>
 

要么

 assert <condition> : <object>
 

其中<condition>是一个布尔表达式,<object>是一个对象,其toString()方法的输出将包含在错误中.

如果条件不是真的,assert语句抛出Error(AssertionError).默认情况下,Java忽略断言.您可以通过将选项-ea传递给JVM来启用断言.您可以启用并禁用单个类和包的断言.这意味着您可以在开发和测试时使用断言验证代码,并在生产环境中禁用它们,尽管我的测试显示下一步没有断言的性能影响.

在这种情况下不使用断言是可以的,因为代码只会失败,这是如果使用断言会发生的事情.唯一的区别是,对断言,它可能会更快发生,更有意义的方式,并且可能带有额外的信息,这可能有助于您弄清楚如果您不期望它为什么会发生这种情况.

(1)有点难.如果您对所调用的代码没有控制权,那么您就会被卡住.如果null是有效的响应,则必须检查它.

但是,如果它是你控制的代码(通常情况是这样),那么它是一个不同的故事.避免使用nulls作为响应.使用返回集合的方法,很容易:返回空集合(或数组)而不是nulls几乎所有时间.

使用非集合可能更难.考虑这是一个例子:如果您有这些接口:

 public interface Action {
  void doSomething();
}

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

其中Parser接受原始用户输入并找到需要做的事情,也许如果您正在为某些东西实现命令行接口.现在,如果没有适当的操作,您可能会签订返回null的合同.这导致您正在讨论的null检查.

另一个解决方案是永远不返回null,而是使用 Null对象模式:

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

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

这是一个更好的设计,因为它会导致更简洁的代码。

尽管如此,也许findAction()方法使用有意义的错误消息抛出异常是完全适当的 – 特别是在这种情况下,您依赖于用户输入.使用findAction方法抛出异常比调用方法在没有解释的情况下打击简单的NullPointerException更好.

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

或者,如果您认为 try/catch 机制太丑,而不是 Do Noth 您的默认操作应该向用户提供反馈。

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

  相同标签的其他问题

javaobjectnullpointerexceptionnull