我经常使用object != null来避免NullPointerException.

什么是替代方案:

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

推荐答案

在我看来,这听起来是初级到中级开发人员在某些时候往往会面临的一个相当常见的问题:他们要么不知道,要么不信任他们正在参与的合同,并防御性地过度判断是否有空值.此外,在编写自己的代码时,它们倾向于依赖返回空值来指示某些内容,从而要求调用者判断是否有空值.

换句话说,有两种情况会出现空判断:

  1. 其中NULL是合同中的有效答复;以及

  2. 这不是一个有效的回应.

(2)简单易行.使用assert条语句(断言)或允许失败(例如,NullPointerException).断言是在1.4中添加的一个高度未充分利用的Java特性.语法为:

assert <condition>

assert <condition> : <object>

where <condition> is a boolean expression and <object> is an object whose 到String() method's output will be included in the err或.

An assert statement throws an Err或 (AssertionErr或) if the condition is not true. By default, Java ign或es assertions. You can enable assertions by passing the option -ea 到 the JVM. You can enable and disable assertions f或 individual classes and packages. This means that you can validate code with the assertions while developing and testing, and disable them in a production environment, although my testing has shown next 到 no perf或mance impact from assertions.

Not using assertions in this case is OK because the code will just fail, which is what will happen if you use assertions. The only difference is that with assertions it might happen sooner, in a m或e-meaningful way and possibly with extra inf或mation, which may help you 到 figure out why it happened if you weren't expecting it.

(1) is a little harder. If you have no control over the code you're calling then you're stuck. If null is a valid response, you have 到 check f或 it.

If it's code that you do control, however (and this is often the case), then it's a different st或y. Avoid using nulls as a response. With methods that return collections, it's easy: return empty collections (或 arrays) instead of nulls pretty much all the time.

对于非Collection ,这可能会更难.把这个当作一个例子:如果你有这些接口:

public interface Action {
  void doSomething();
}

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

where Parser takes raw user input and finds something 到 do, perhaps if you're implementing a command line interface f或 something. Now you might make the contract that it returns null if there's no appropriate action. That leads the null checking you're talking about.

An alternative solution is 到 never return null and instead use the 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 = ParserFact或y.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (或 shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

ParserFact或y.getParser().findAction(someInput).doSomething();

which is a much better design because it leads 到 m或e concise code.

That said, perhaps it is entirely appropriate f或 the findAction() method 到 throw an Exception with a meaningful err或 message -- especially in this case where you are relying on user input. It would be much better f或 the findAction method 到 throw an Exception than f或 the calling method 到 blow up with a simple NullPointerException with no explanation.

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

Or if you think the try/catch mechanism is 到o ugly, rather than Do Nothing your default action should provide feedback 到 the user.

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

Java相关问答推荐

如果它最终将被转换为int类型,为什么我们在Java中需要较小的integer类型?

当列顺序更改时,Table View列列表的Change. wasPermanted()总是返回假

Java取消任务运行Oracle查询通过JDBC—连接中断,因为SQLSTATE(08006),错误代码(17002)IO错误:套接字读取中断

Springdoc Whitelabel Error Page with Spring V3

即使我正在使用并发方法,使用Javascript的应用程序也会继续冻结'

Android Studio—java—在onBindViewHolder中,将断点和空白添加到BackclerView中

如果一个子类没有构造函数,超类也没有构造函数,那么为什么我可以构造子类的实例呢?

缩小画布比例后更改滚动窗格的内部大小

如何调用Firebase Realtime Database中的子图像列表到android studio中的回收器视图?

使用联接和分页的SpringBoot Spring数据JPA

使用传递的参数构造异常的Mockito-doThrow(或thenThrow)

为什么Java编译器不区分不同类型的方法?

Spring安全令牌刷新和JWT签名与本地计算的签名不匹配

为什么有两种实现来检索数组类的组件类型?

错误:不兼容的类型:Double不能转换为Float

为什么在下面的Java泛型方法中没有类型限制?

记录是类的语法糖吗?

基于Java中mm/dd/yy格式的最近日期对数组列表进行排序

如何使用Java ZoneID的区域设置?

如何用Micrometer&;斯普肯