当前位置: 首页 > 面试题库 >

Java 空检查链与捕获NullPointerException

李宜然
2023-03-14
问题内容

Web服务返回一个巨大的XML,我需要访问它的深层嵌套字段。例如:

return wsObject.getFoo().getBar().getBaz().getInt()

问题是getFoo()getBar()getBaz()可能所有的回报null

但是,如果我null在所有情况下都进行检查,则代码将变得非常冗长且难以阅读。此外,我可能会错过某些领域的检查。

if (wsObject.getFoo() == null) return -1;
if (wsObject.getFoo().getBar() == null) return -1;
// maybe also do something with wsObject.getFoo().getBar()
if (wsObject.getFoo().getBar().getBaz() == null) return -1;
return wsObject.getFoo().getBar().getBaz().getInt();

可以写吗

try {
    return wsObject.getFoo().getBar().getBaz().getInt();
} catch (NullPointerException ignored) {
    return -1;
}

或将其视为反模式?


问题答案:

捕获NullPointerException是一件非常有问题的事情,因为它们几乎可以在任何地方发生。从错误中获取一个错误,意外地捕获它,然后像一切正常一样继续进行非常容易,从而隐藏了一个真正的问题。处理起来非常棘手,因此最好完全避免。(例如,考虑对null进行自动拆箱Integer。)

我建议你改用Optional该类。当你要使用存在或不存在的值时,这通常是最好的方法。

使用它,你可以这样编写代码:

public Optional<Integer> m(Ws wsObject) {
    return Optional.ofNullable(wsObject.getFoo()) // Here you get Optional.empty() if the Foo is null
        .map(f -> f.getBar()) // Here you transform the optional or get empty if the Bar is null
        .map(b -> b.getBaz())
        .map(b -> b.getInt());
        // Add this if you want to return an -1 int instead of an empty optional if any is null
        // .orElse(-1);
        // Or this if you want to throw an exception instead
        // .orElseThrow(SomeApplicationException::new);
}

为什么可选?
使用Optionals代替null可能不存在的值使事实对于读者来说非常明显和清楚,并且类型系统将确保你不会意外忘记它。

你还可以访问更方便地使用这些值的方法,例如maporElse

缺席有效还是错误?
但是还要考虑中间方法返回null是否是有效结果,或者这是错误的征兆。如果始终是错误,则抛出异常可能比返回特殊值或使中间方法本身抛出异常更好。

也许还有更多可选件?
另一方面,如果中间方法中缺少的值仍然有效,也许你也可以将Optional它们切换为s?

然后,你可以像这样使用它们:

public Optional<Integer> mo(Ws wsObject) {
    return wsObject.getFoo()
        .flatMap(f -> f.getBar())
        .flatMap(b -> b.getBaz())
        .flatMap(b -> b.getInt());        
}

为什么不选?
我能想到的不使用的唯一原因Optional是,这是否在代码的性能关键部分,以及垃圾回收的开销是否是一个问题。这是因为Optional每次执行代码时都会分配一些对象,而VM 可能无法对其进行优化。在这种情况下,你的原始if测试可能会更好。



 类似资料:
  • 一个web服务返回一个巨大的XML,我需要访问它的深度嵌套字段。例如: 问题是、、都可能返回。 但是,如果我在所有情况下都检查,那么代码就会变得非常冗长,很难阅读。此外,我可能会错过一些字段的支票。 可以写吗 或者这会被认为是反模式吗?

  • 我已为单链表创建了此节点类:  我想在名为findmax的方法中搜索具有最高键的节点。但是我想检查列表是否为空,如果为空,则返回null,否则返回具有最高密钥的节点。这就是我所做的: 我只想知道我检查列表是否为空是否正确。

  • 问题内容: 假设我要执行以下命令: 为了避免NullPointerException,如果发生以下情况,我将必须执行以下操作: 有没有一种方法或已经存在的Utils类可以更优雅地做到这一点,让我们说以下类似的东西? 问题答案: 最好的方法是 避免 连锁。如果您不熟悉Demeter法则(LoD),我认为应该这样做。您已经给出了一个完美的消息链示例,该消息链与没有业务知识的类过于亲密。 得墨meter

  • 有人能解释一下<code>是可选的</code>如何帮助我们避免<code>NullPointerException</code>吗? 这段代码不是也容易出现<code>NullPointerException</code>吗?如果是这样的话,那么为什么这个代码比其他代码更受欢迎 除了帮助我们了解函数是否实际具有返回值之外,还提供了什么可能的好处

  • 我有一个带有(?:)格式的非捕获组的java正则表达式,我不明白为什么它为非捕获组提供“null”匹配。 如果我将下面的正则表达式缩短为“@te(st)(?:AA)?”使用相同的?:非捕获组,它给出了我认为的预期行为,只匹配1个组和完全匹配。

  • 问题内容: 我正在为Android开发Java应用程序,目前遇到了一个问题,调试器正在进入catch块,并且ex为何为null?有人看过这样的东西吗? 问题答案: 这听起来像源代码,并且编译的类不同步,因此调试器正在进入错误的块。 尝试进行清理,然后进行重建。