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

查看:45
本文介绍了空检查链与捕获 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真正有问题的事情,因为它们几乎可以在任何地方发生.很容易从错误中得到一个,偶然发现它并继续,好像一切正​​常,从而隐藏一个真正的问题.处理起来非常棘手,因此最好完全避免.(例如,考虑自动拆箱 null 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.)

我建议您使用 可选 类.当您想要处理存在或不存在的值时,这通常是最佳方法.

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 s?

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.

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

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