Optional乱用Empty之No value present

前言

看到好多文章都是推荐采用Optinal的,而经常我遇到问题的时候就想:如果设计成optional的话就不会忽略这种NullPointException错误了。然而,optional并不是想用就随便用的。今天花了10分钟追踪一个bug,根源就是optional滥用。

问题描述

API返回失败,没有描述原因。看着蛋疼,因为公开的API不方便返回错误详情。于是查log,发现错误日志的message为:No value present。没搞清楚这个错误信息是哪一层跑出来的。需要进一步跟踪。A=>B=>C=>D,一直追踪到C层才找到问题。

问题代码如下:

public FieldBuilder withSubcategoryId(Optional<String> id) {
    this.id = id.get();
    return this;
}

这是一个创建工厂类,负责创建一个可以使用对象。所有的字段都采用了Opetional的包裹。这个是对象,理应不包含业务逻辑,应该没有错误异常。如果有异常应该显式的throws出来,不然这个非检查性异常将在出现bug的时候难以定位。而这里确实有一个异常没有捕获,而且也不能保证不会发生,甚至就是这里引起的bug:java.util.Optional#get

源码如下:

/**
 * If a value is present in this {@code Optional}, returns the value,
 * otherwise throws {@code NoSuchElementException}.
 *
 * @return the non-null value held by this {@code Optional}
 * @throws NoSuchElementException if there is no value present
 *
 * @see Optional#isPresent()
 */
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

虽然没有显式的抛出异常,但在javadoc中写清楚了会出现的问题。而我们这些新手则没有认真看文档就想当然的采用了。以为当内容为null的时候get出来的还是null

Find Uage找这个Builder的用法发现:

new FieldBuilder().withSubcategoryId(Optional.ofNullable(entity.getSubcategoryId()))

这里直接使用了Optional.OfNullable。然而,我们知道在下一步中会调用get,get的时候回判断是否是nullnull会抛出异常。这简直就是自己挖坑,写一个条件抛异常,而传参数又专门去符合这个条件。前面也没有校验,外面也没有捕获异常,最终导致异常直接一路抛出到API外层去了。

结论

Optional不要滥用,Optional不是安全的随便用的,Optional用的时候记得捕获异常。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术栈

强悍!Java 9 中的9个新特性

来源:www.oschina.net/translate/java-9-new-features ? 你可能已经听说过 Java 9 的模块系统,但是这个新版本...

3128
来自专栏程序猿DD

优雅处理你的Java异常

来源:https://my.oschina.net/c5ms/blog/1827907

922
来自专栏xingoo, 一个梦想做发明家的程序员

Spark源码分析 之 Driver和Excutor是怎么跑起来的?(2.2.0版本)

今天抽空回顾了一下Spark相关的源码,本来想要了解一下Block的管理机制,但是看着看着就回到了SparkContext的创建与使用。正好之前没有正式的整理...

1899
来自专栏前端架构

旧调重弹Hibernate与Ibatis区别——深入架构设计

对于一个粗学者而言一言概况就是:ibatis非常简单易学,hibernate相对较复杂,门槛较高。 

724
来自专栏开发与安全

linux系统编程之基础必备(一):计算机体系结构一点基础知识

下面这张图来自《深入理解计算机系统》: IO桥部分一般还分为北桥和南桥,北桥当然是靠上的了。 ? •CPU –主频:  CPU的时钟频率,内核工作的时钟频...

1815
来自专栏技术墨客

Spring核心——上下文与IoC 原

前面3篇分别介绍了IoC容器与Bean的关系、Bean与Bean之间的关系以及Bean自身的控制和管理。在了解Spinrg核心模式时,一定要谨记他的基本工作元素...

673
来自专栏微信公众号:Java团长

Java后端程序员1年工作经验总结

  毕业已经一年有余,这一年里特别感谢技术管理人员的器重,以及同事的帮忙,学到了不少东西。这一年里走过一些弯路,也碰到一些难题,也受到过做为一名开发却经常为系统...

1052
来自专栏Java技术分享

Java9 中的 9 个新特性

你可能已经听说过 Java 9 的模块系统,但是这个新版本还有许多其它的更新。 这里有九个令人兴奋的新功能将与 Java 9 一起发布。 1. Java 平台级...

1769
来自专栏一个会写诗的程序员的博客

Java 9 新特性 极简介绍

Java 9 的定义功能是一套全新的模块系统。当代码库越来越大,创建复杂,盘根错节的“意大利面条式代码”的几率呈指数级的增长。这时候就得面对两个基础的问题: 很...

412
来自专栏jessetalks

异步编程 In .NET

概述   在之前写的一篇关于async和await的前世今生的文章之后,大家似乎在async和await提高网站处理能力方面还有一些疑问,博客园本身也做了不少的...

2886

扫描关注云+社区