空检查链 vs 捕获 NullPointerException [英] Null check chain vs catching NullPointerException

查看:39
本文介绍了空检查链 vs 捕获 NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

A web service returns a huge XML and I need to access deeply nested fields of it. For example:

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

问题是getFoo()getBar()getBaz()都可能返回null.

The problem is that getFoo(), getBar(), getBaz() may all return null.

然而,如果我在所有情况下都检查 null,代码就会变得非常冗长且难以阅读.此外,我可能会错过某些字段的检查.

However, if I check for null in all cases, the code becomes very verbose and hard to read. Moreover, I may miss the checks for some of the fields.

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

或者这会被视为反模式吗?

or would that be considered an antipattern?

推荐答案

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

Catching NullPointerException is a really problematic thing to do since they can happen almost anywhere. It's very easy to get one from a bug, catch it by accident and continue as if everything is normal, thus hiding a real problem. It's so tricky to deal with so it's best to avoid altogether. (For example, think about auto-unboxing of a null Integer.)

我建议你使用 Optional 类代替.当您想要处理存在或不存在的值时,这通常是最好的方法.

I suggest that you use the Optional class instead. This is often the best approach when you want to work with values that are either present or absent.

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

Using that you could write your code like this:

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 null instead of an empty optional if any is null
        // .orElse(null);
        // Or this if you want to throw an exception instead
        // .orElseThrow(SomeApplicationException::new);
}

<小时>

为什么是可选的?

对于可能不存在的值,使用 Optionals 而不是 null 使这一事实对读者非常明显和清晰,并且类型系统将确保您不会不小心忘记了.


Why optional?

Using Optionals instead of null for values that might be absent makes that fact very visible and clear to readers, and the type system will make sure you don't accidentally forget about it.

您还可以更方便地访问处理这些值的方法,例如 maporElse.

You also get access to methods for working with such values more conveniently, like map and orElse.

但也要考虑中间方法返回 null 是否是有效结果,或者这是否是错误的迹象.如果始终是错误,那么抛出异常可能比返回特殊值或中间方法本身抛出异常更好.

But also think about if it is a valid result for the intermediate methods to return null or if that is a sign of an error. If it is always an error then it's probably better throw an exception than to return a special value, or for the intermediate methods themselves to throw an exception.

另一方面,如果中间方法中缺少的值是有效的,也许您也可以为它们切换到 Optional ?

If on the other hand absent values from the intermediate methods are valid, maybe you can switch to Optionals for them also?

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

Then you could use them like this:

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 测试可能会更好.


Why not optional?

The only reason I can think of for not using Optional is if this is in a really performance critical part of the code, and if garbage collection overhead turns out to be a problem. This is because a few Optional objects are allocated each time the code is executed, and the VM might not be able to optimize those away. In that case your original if-tests might be better.

这篇关于空检查链 vs 捕获 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆