热门系列:


目录

1.前序

2.正文

2.1 Optional的起源

2.2 Optional使用场景

2.2.1 为什么要用?

2.2.2 什么场景用?

2.3 常用方法使用

2.3.1 empty()

2.3.2 of()

2.3.3 ofNullable()

2.3.4 isPresent()

2.3.5 get()

2.3.6 ifPresent()

2.3.7 filter()

2.3.8 map()

2.3.9 flatMap()

2.3.10 orElse()

2.3.11 orElseGet()

2.3.12 orElseThrow()

3.总结


1.前序

JDK8是Oracle在2014年3月19日发布正式版的,和JDK7(2011年7月发布)相隔了近3年(拖的时间堪比JDK7和JDK6之间的时间,与历史版本发布间隔相比排在第二位,JDK6发布是2006,JDK7与之相比之间差了5年,这两个版本发布时间间隔最长,中间发生了Oracle收购SUN的大事件,JDK6因此曾成为使用率最高的JDK,),中间因意见不统一多次延迟。

距离现在已经近6年了。但是,目前仍然有很多公司在使用此版本作为开发版本!(至少我目前所呆的公司仍在使用,各位目前常用的是哪个版本呢?欢迎留言。。。)

但是为什么现在才拿出来记录呢。。。。当然是因为,我乐意啊,,哈哈。。(其实是最近有时间了,想要做一个Java 8系列的博文集啦)

最近,我会不定期,持续输出Java 8新特性且常用的一些技术点,例如OptionalLambda表达式和函数式接口、Stream、日期时间API、重复注释、类型推断、 注解的扩展等等,与大家一起分享并记录!感兴趣,可以插个眼~~~!好了,今天先和大家一起扒一扒如题的判空类:Optional


2.正文

2.1 Optional的起源

著名的 NullPointerException 是引起系统失败最常见的原因。很久以前Google Guava项目引入了Optional作为解决空指针异常的一种方式,不赞成代码被null检查的代码污染,期望程序员写整洁的代码。受Google Guava的鼓励,Optional 现在是Java 8库的一部分。

Optional 只是一个容器,它可以保存一些类型的值或者null。它提供很多有用的方法,如官方文档API所示:

修饰符和类型 方法和说明
static <T> Optional<T> empty()

返回一个空Optional实例。
boolean equals(Object obj)

指示其他某个对象是否“等于”此Optional。
Optional<T> filter(Predicate<? super T> predicate)

如果存在一个值,并且该值与给定的谓词匹配,则返回一个Optional描述值的描述,否则返回一个empty Optional
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

如果存在值,则将提供的Optional-bearing映射函数应用于该值,返回该结果,否则返回empty Optional
T get()

如果此值存在Optional,则返回该值,否则抛出NoSuchElementException
int hashCode()

返回当前值的哈希码值(如果有);如果没有值,则返回0(零)。
void ifPresent(Consumer<? super T> consumer)

如果存在值,请使用该值调用指定的使用者,否则不执行任何操作。
boolean isPresent()

true如果存在值,则返回,否则返回false
<U> Optional<U> map(Function<? super T,? extends U> mapper)

如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回Optional描述结果的描述。
static <T> Optional<T> of(T value)

返回Optional具有指定的当前非空值的。
static <T> Optional<T> ofNullable(T value)

返回Optional描述指定值的描述,如果不为null,则返回null Optional
T orElse(T other)

返回值(如果存在),否则返回other
T orElseGet(Supplier<? extends T> other)

返回值(如果存在),否则调用other并返回该调用的结果。
<X extends Throwable>
T
orElseThrow(Supplier<? extends X> exceptionSupplier)

返回包含的值(如果存在),否则抛出异常,由提供的供应商创建。
String toString()

返回此Optional的非空字符串表示形式,适用于调试。

但实际上,JDK1.8中Optional 总共有17个方法, 除去两个私有的构造方法, 除去equals, hashCode, toString三个方法外,;只剩下12个 Optional 提供的方法。

2.2 Optional使用场景

2.2.1 为什么要用?

在使用一个技术之前,我们必须要做一些思考,这样是很有必要的!能帮我更好的做到:知其然,知其所以然;(其实说简单点,就是防止少挖坑,骚年,醒醒吧!!你的bug还没有修复完~~~)

先说说为什么要用!!试想一下,你的代码或者你的小伙伴的代码中,你是否或多或少的见过类似如下的这些代码:

String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();//将上面的代码进行判空处理
if (user != null) {Address address = user.getAddress();if (address != null) {Country country = address.getCountry();if (country != null) {String isocode = country.getIsocode();if (isocode != null) {isocode = isocode.toUpperCase();}}}
}

尤其是,当有很大一段业务逻辑处理的时候,你会发现,代码不光看起来很臃肿,并且难以阅读,可读性很差!那如果我们调整为使用optional来编写的话,可以转换成如下写法:

Optional.ofNullable(user).map(User::getAddress).map(Address::getCountry).map(Country::getIsocode).ifPresent(s-> s.toUpperCase());

如此,代码的可读性和整洁度,都好了许多!并且使用这种链式处理,也能更好的提高开发效率!这也是我们为什么需要用到optional的原因啦!

2.2.2 什么场景用?

我们写代码,在保证业务功能的正确和稳定性的基础之上,才会去考虑代码的可读性与简洁度,而不是一味的追求形式!!否则只会是华而不实,不仅容易出错,更是本末倒置!

个人总结了几点如下:

  • 当使用值为空的情况,并非源于报错时产生,可以使用Optional(因为有错误的情况,肯定是不正常的,需要处理的)

  • 对于一个对象,我们需要做判空、过滤、某些校验的时候,可以使用Optional

2.3 常用方法使用

方法介绍顺序,从简单的开始:

2.3.1 empty()

empty 方法返回一个不包含值的 Optional 实例, 注意不保证返回的 empty 是单例, 不要用 == 比较。

    public static<T> Optional<T> empty();

2.3.2 of()

返回一个 Optional 实例;代表指定的非空值, 如果传入 null 会立刻抛出空指针异常。

 public static <T> Optional<T> of(T value);

2.3.3 ofNullable()

  1. 返回一个 Optional 实例, 如果指定非空值则实例包含非空值, 如果传入 null 返回不包含值的 empty
 public static <T> Optional<T> ofNullable(T value);

2.3.4 isPresent()

isPresent 用来判断实例是否包含值, 如果不包含非空值返回 false, 否则返回 true

 public boolean isPresent();

2.3.5 get()

get 方法, 如果实例包含值则返回当前值, 否则抛出 NoSushElementException 异常

 public T get();

2.3.6 ifPresent()

ifPresent 方法作用是当实例包含值时, 来执行传入的 Consumer, 比如调用一些其他方法

public void ifPresent(Consumer<? super T> consumer);

例如如下用法:

public void testIfPresent() {// ifPresent 表示 Optional 中的对象存在才会执行 Consumer 接口对象中的方法List<String> dataList = new ArrayList<>();// 1. 不为空没有值的集合Optional.ofNullable(dataList).ifPresent(t -> {System.out.println("1"); // 输出 1t.forEach(a -> System.out.println(a));});
}

2.3.7 filter()

filter 方法用于过滤不符合条件的值, 接收一个 Predicate 参数, 如果符合条件返回代表值的 Optional 实例, 否则返回 empty;例如:

private static List<User> userList = new ArrayList<>();/*** 初始化 user 集合*/
@Before
public void initEveryTestBefore() {userList.add(new User(22, "王旭", "wang.xu","123456", '1', true));userList.add(new User(21, "孙萍", "sun.ping","a123456", '2', false));userList.add(new User(23, "步传宇", "bu.zhuan.yu", "b123456", '1', false));userList.add(new User(18, "蔡明浩",  "cai.ming.hao","c123456", '1', true));userList.add(new User(17, "郭林杰", "guo.lin.jie", "d123456", '1', false));userList.add(new User(29, "韩凯", "han.kai", "e123456", '1', true));userList.add(new User(22, "韩天琪",  "han.tian.qi","f123456", '2', false));userList.add(new User(21, "郝玮",  "hao.wei","g123456", '2', false));userList.add(new User(19, "胡亚强",  "hu.ya.qing","h123456", '1', false));userList.add(new User(14, "季恺",  "ji.kai","i123456", '1', false));userList.add(new User(17, "荆帅",  "jing.shuai","j123456", '1', true));userList.add(new User(16, "姜有琪",  "jiang.you.qi","k123456", '1', false));logger.info("initEveryTestBefore, size {}", userList.size());
}// filter: optional 中的对象在不为空,并且满足某个条件的时候才会返回
@Test
public void testFilter() {// 1. 在集合中有年龄大于 18 岁的才会返回所有对象Optional.ofNullable(userList).filter(t -> t.stream().anyMatch(u -> u.getAge() > 18)).ifPresent(t -> {t.forEach(u -> {System.out.println("1:" + u.toString());});});// 2. 因为集合中没有年龄大于 50 岁的,因此不会返回任何对象Optional.ofNullable(userList).filter(t -> t.stream().anyMatch(u -> u.getAge() > 50)).ifPresent(t -> {t.forEach(u -> {System.out.println("2:" + u.toString());});});
}

2.3.8 map()

map 方法是链式调用避免空指针的核心方法, 当实例包含值时, 对值执行传入的 Function 逻辑, 并返回一个代表结果值的新的 Optional 实例;也就是将 optional 中的对象转成 其他对象,或者修改对象中的属性;如:

// 1. 返回 optional 中的对象年龄在 18 岁以上的
Optional.ofNullable(userList).map(t -> {List<User> tempList = new ArrayList<>();t.forEach(u -> {if (u.getAge() > 18) {tempList.add(u);}});return tempList;}).ifPresent(t -> {t.forEach(u -> {System.out.println("1:" + u.toString());});});

2.3.9 flatMap()

flatMap方法是将 optional 中的对象转成 optional 对象,或者修改对象中的属性;与map方法类似。不同之处在于:

Optional.ofNullable(userList).map(t -> {List<User> tempList = new ArrayList<>();t.forEach(u -> {if (u.getAge() > 18) {tempList.add(u);}});//不同之处return Optional.of(tempList);})

2.3.10 orElse()

orElse方法是如果实例包含值, 那么返回这个值, 否则返回指定的默认值, 如null

public T orElse(T other);

2.3.11 orElseGet()

orElseGet方法是如果实例包含值, 返回这个值;否则,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果。

public T orElseGet(Supplier<? extends T> other);

orElse与orElseGet不同之处:

public void givenPresentValue_whenCompare_thenOk() {User user = new User("john@gmail.com", "1234");logger.info("Using orElse");User result = Optional.ofNullable(user).orElse(createNewUser());logger.info("Using orElseGet");User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
}

输出结果:

Using orElse
Creating New User
Using orElseGet

2.3.12 orElseThrow()

如果实例不包含值, 调用传入的 Supplier 参数, 生成一个异常实例并抛出.这个方法通常与全局异常处理器一起使用, 当参数或者其他情况获取不到值时, 抛出自定义异常, 由异常处理器处理成通用返回结果, 返回给前端;如:

Optional.ofNullable(tempList).orElseThrow(() -> runtimeException).forEach(t -> System.out.println("2:" + t));

3.总结

以上即为JDK1.8新增的Optional类的常用方法及场景记录!举例的代码方面,比较零散,但主要是为了方便大家有一个功能使用和方法差别上的了解!(所以,不要在意那些鸡零狗碎的代码意义~~~~)

路漫漫,其修远兮!欢迎大家提问、留言!!!

微信同款:https://mp.weixin.qq.com/s/jhJBI6uK6bvCBTUxnj-LUA

【Java 8系列】Java开发者的判空利器 -- Optional相关推荐

  1. java实体类及类属性判空

    敲代码时判空是必须的,这里分享一下java实体类及类属性判空体会. 一.实体类判空: 1.1实体类判空 如果是读库返回实体类,我们直接判空即可,如下图 1.2如果是先定义了类就不能这样判空了,因为ne ...

  2. java集合系列——java集合概述(一)

    在JDK中集合是很重要的,学习java那么一定要好好的去了解一下集合的源码以及一些集合实现的思想! 一:集合的UML类图(网上下载的图片) Java集合工具包位置是java.util.* 二:集合工具 ...

  3. java list 去空字符串_【JAVA基础】list和字符串判空

    前言: 我们在项目中经常需要对获取的list集合或String类型变量判空,看前辈的代码,不同的人判空的方法不一样,那么,Java代码中,对list集合和String类型变量到底该如何判空呢? 一.J ...

  4. java判空null前后,关于java:引不要再使用null判空了

    以下文章来源于Hollis ,作者上帝爱吃苹果 对于Java程序员来说,null是令人头痛的货色.时常会受到空指针异样(NPE)的骚扰.连Java的发明者都抵赖这是他的一项微小失误. 那么,有什么方法 ...

  5. Java妙手判空之Optional

    我们有个对象需要对里面的errmsg和PhoneInfo里面的属性的字段进行判空 GetUserPhoneNumberResDto: @Data public class GetUserPhoneNu ...

  6. java虚拟机系列:java虚拟机内存模型

    java内存模型,分为程序计数器,虚拟机栈,本地方法栈,java堆,java栈.根据受访的权限不同设置,可以分为线程共享和线程私有.线程共享指可以允许所有的线程共享访问的一类内存区域,包括堆内存区,方 ...

  7. 小明学java基础系列——Java 类加载

    Java类加载学习笔记 一.基本概念 1.1 基本文件类型和概念 1.2 idea程序示例 1.2.1 idea-java源文件 1.2.2 idea-java字节码 1.2.3 idea-类加载 1 ...

  8. Java入门系列——Java语言基础(小康小白)

    我是小康小白,一个平平无奇的Java,Python小白.热爱有趣的文字,生活和远方. 个人博客:https://blog.csdn.net/weixin_45791445 有问题欢迎QQ联系:1059 ...

  9. Java 密码系列 - Java 和 JS Base 64

    Base 64 不属于密码技术,仅是编码方式.但由于在 Java.JavaScript.区块链等出现的频率较高,故在本系列文章中首先分享 Base 64 编码技术.前面部分主要介绍 Base 64 理 ...

最新文章

  1. HDU - 4607 Park Visit (树的直径)
  2. PostGis加载空间数据
  3. User-Item协同自回归模型的协同过滤
  4. 【转载】MSDN上发现了一篇很好的WCF入门教程
  5. 传输预编码matlab,无线通信-预编码-MATLAB代码合集-毕设专用.zip
  6. java 打印机类printer_Spring案例打印机的实现过程详解
  7. Computer Hardware ID(CHID)及驱动推送
  8. 网页打不开显示php探针,phpinfo被禁用,可用php探针
  9. 小米android11账号补丁,小米9 MIUI11 解账户锁 可登小米账号 永不反锁 完美ROOT 解锁包...
  10. 软件测试培训班出来好找工作么
  11. Ruby + Passenger 5 分钟 入门
  12. 【知识图谱】实践篇——基于医疗知识图谱的问答系统实践(Part2):图谱数据准备与导入
  13. BZOJ 3687 简单题
  14. JQuery制作飘落的树叶动画效果
  15. 啊5G 你比4G多1G
  16. 人机大战,历史的见证
  17. php 抽象工厂模式,PHP设计模式(三)抽象工厂模式(Abstract Factory)
  18. 连接Basler相机
  19. 【网络工程师】<软考中级>无线通信网
  20. 遭索赔800万 索尼成被告

热门文章

  1. 《Android 软件安全与逆向分析》---- 学习笔记
  2. 上车是什么意思_老司机,“上车”的意思,你真的懂吗?
  3. utrack调试 艾肯icon_艾肯(iCON)Utrack声卡K歌设置图文教程
  4. mysql数据库命中率_Oracle数据库关于命中率的查询语句总结
  5. html中怎样写渐变色代码,纯css简单几行代码实现颜色渐变效果 非常漂亮
  6. 365天深度学习训练营-第P7周:咖啡豆识别
  7. 对数函数定义域和值域_对数函数的定义域、值域、定点
  8. 在线扫描php后门_解密php webshell后门
  9. 眼疾手快,真男人就来合成粽子三兄弟
  10. Curio for Mac(头脑风暴思维导图)