一个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;
}
或者这会被认为是反模式吗?
我建议考虑objects.requirenonnull(T obj,String message)
。您可以为每个异常创建一个详细消息的链,如
requireNonNull(requireNonNull(requireNonNull(
wsObject, "wsObject is null")
.getFoo(), "getFoo() is null")
.getBar(), "getBar() is null");
我建议您不要使用特殊的返回值,如-1
。那不是Java的风格。Java设计了异常机制来避免这种来自C语言的老式方法。
抛出NullPointerException
也不是最佳选择。您可以提供自己的异常(选中它以确保用户可以处理它,或者取消选中它以更简单的方式处理它),或者使用您正在使用的XML解析器中的特定异常。
捕获NullPointerException
确实是一个问题,因为它们几乎可以在任何地方发生。从一个bug那里得到一个是非常容易的,偶然抓住它并继续,好像一切正常一样,从而隐藏了一个真正的问题。这是如此棘手的处理,所以最好是避免完全。(例如,考虑自动取消空整数
的装箱。)
我建议您改用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 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);
}
对于可能不存在的值,使用optional
s而不是null
可以使读者非常清楚地看到这一事实,并且类型系统将确保您不会意外地忘记这一点。
您还可以更方便地访问用于处理此类值的方法,如map
和orelse
。
而且还要考虑中间方法返回null是否是一个有效的结果,或者这是否是一个错误的标志。如果总是一个错误,那么抛出一个异常可能比返回一个特殊值更好,或者中间方法本身抛出一个异常更好。
另一方面,如果中间方法中不存在的值是有效的,也许您也可以为它们切换到optional
?
那么您可以这样使用它们:
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,我需要访问它的深层嵌套字段。例如: 问题是,,可能所有的回报。 但是,如果我在所有情况下都进行检查,则代码将变得非常冗长且难以阅读。此外,我可能会错过某些领域的检查。 可以写吗 或将其视为反模式? 问题答案: 捕获是一件非常有问题的事情,因为它们几乎可以在任何地方发生。从错误中获取一个错误,意外地捕获它,然后像一切正常一样继续进行非常容易,从而隐藏了一个
问题内容: 这是下面的代码: 如果值是我仍然得到未选中的框。我是不是应该从上面做错事,应该工作? 有任何想法吗? 问题答案: 使用is_null或运算符。
有人能解释一下如何帮助我们避免? 这段代码不是也容易出现吗?如果是这样的话,那么为什么这个代码比 除了帮助我们了解函数是否实际具有返回值之外,还有什么可能的好处
问题内容: 我的老板说我应该使用,因为它比更好,但是他不记得为什么这样做。有什么理由要使用吗? 我以某种方式感觉到…相反! 在Google上进行搜索后,我发现的唯一结果是: 在C语言中,它可以防止您意外地在条件结构中键入(obj = null)。 问题答案: 您不能通过输入来意外分配给它。但是,这是C时代的回忆,在Java中是不可能的,因为表达式返回赋值的右侧。由于不是,编译器会抱怨。 我会尽力向
问题内容: 在Java中,引发 检查 异常(Exception或其子类型- IOException,InterruptedException等)的方法必须声明 throws 语句: 不声明语句的 方法不能 引发检查的异常。 但是在Java中使用安全方法捕获检查的异常仍然合法: 其实没有 有点可笑:编译器知道 e 不是检查的异常,因此可以将其重新抛出。事情甚至有些荒谬,此代码无法编译: 第一个片段是