【Java 8系列】Java开发者的判空利器 -- Optional
热门系列:
【Java 8系列】收集器Collector与工具类Collectors
【Java 8系列】Stream详解,看这一篇就够啦
【Java 8系列】Lambda 表达式,一看就废
【Java 8系列】Java日期时间的新主宰者:LocalDate、LocalTime、LocalDateTime、ZonedDateTime
程序人生,精彩抢先看
目录
1.前序
距离现在已经近6年了。但是,目前仍然有很多公司在使用此版本作为开发版本!(至少我目前所呆的公司仍在使用,各位目前常用的是哪个版本呢?欢迎留言。。。)
但是为什么现在才拿出来记录呢。。。。当然是因为,我乐意啊,,哈哈。。(其实是最近有时间了,想要做一个Java 8系列的博文集啦)
2.正文
2.1 Optional的起源
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>
|
orElseThrow(Supplier<? extends X> exceptionSupplier)
返回包含的值(如果存在),否则抛出异常,由提供的供应商创建。
|
String
|
toString()
返回此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()
- 返回一个 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相关推荐
- java实体类及类属性判空
敲代码时判空是必须的,这里分享一下java实体类及类属性判空体会. 一.实体类判空: 1.1实体类判空 如果是读库返回实体类,我们直接判空即可,如下图 1.2如果是先定义了类就不能这样判空了,因为ne ...
- java集合系列——java集合概述(一)
在JDK中集合是很重要的,学习java那么一定要好好的去了解一下集合的源码以及一些集合实现的思想! 一:集合的UML类图(网上下载的图片) Java集合工具包位置是java.util.* 二:集合工具 ...
- java list 去空字符串_【JAVA基础】list和字符串判空
前言: 我们在项目中经常需要对获取的list集合或String类型变量判空,看前辈的代码,不同的人判空的方法不一样,那么,Java代码中,对list集合和String类型变量到底该如何判空呢? 一.J ...
- java判空null前后,关于java:引不要再使用null判空了
以下文章来源于Hollis ,作者上帝爱吃苹果 对于Java程序员来说,null是令人头痛的货色.时常会受到空指针异样(NPE)的骚扰.连Java的发明者都抵赖这是他的一项微小失误. 那么,有什么方法 ...
- Java妙手判空之Optional
我们有个对象需要对里面的errmsg和PhoneInfo里面的属性的字段进行判空 GetUserPhoneNumberResDto: @Data public class GetUserPhoneNu ...
- java虚拟机系列:java虚拟机内存模型
java内存模型,分为程序计数器,虚拟机栈,本地方法栈,java堆,java栈.根据受访的权限不同设置,可以分为线程共享和线程私有.线程共享指可以允许所有的线程共享访问的一类内存区域,包括堆内存区,方 ...
- 小明学java基础系列——Java 类加载
Java类加载学习笔记 一.基本概念 1.1 基本文件类型和概念 1.2 idea程序示例 1.2.1 idea-java源文件 1.2.2 idea-java字节码 1.2.3 idea-类加载 1 ...
- Java入门系列——Java语言基础(小康小白)
我是小康小白,一个平平无奇的Java,Python小白.热爱有趣的文字,生活和远方. 个人博客:https://blog.csdn.net/weixin_45791445 有问题欢迎QQ联系:1059 ...
- Java 密码系列 - Java 和 JS Base 64
Base 64 不属于密码技术,仅是编码方式.但由于在 Java.JavaScript.区块链等出现的频率较高,故在本系列文章中首先分享 Base 64 编码技术.前面部分主要介绍 Base 64 理 ...
最新文章
- HDU - 4607 Park Visit (树的直径)
- PostGis加载空间数据
- User-Item协同自回归模型的协同过滤
- 【转载】MSDN上发现了一篇很好的WCF入门教程
- 传输预编码matlab,无线通信-预编码-MATLAB代码合集-毕设专用.zip
- java 打印机类printer_Spring案例打印机的实现过程详解
- Computer Hardware ID(CHID)及驱动推送
- 网页打不开显示php探针,phpinfo被禁用,可用php探针
- 小米android11账号补丁,小米9 MIUI11 解账户锁 可登小米账号 永不反锁 完美ROOT 解锁包...
- 软件测试培训班出来好找工作么
- Ruby + Passenger 5 分钟 入门
- 【知识图谱】实践篇——基于医疗知识图谱的问答系统实践(Part2):图谱数据准备与导入
- BZOJ 3687 简单题
- JQuery制作飘落的树叶动画效果
- 啊5G 你比4G多1G
- 人机大战,历史的见证
- php 抽象工厂模式,PHP设计模式(三)抽象工厂模式(Abstract Factory)
- 连接Basler相机
- 【网络工程师】<软考中级>无线通信网
- 遭索赔800万 索尼成被告
热门文章
- 《Android 软件安全与逆向分析》---- 学习笔记
- 上车是什么意思_老司机,“上车”的意思,你真的懂吗?
- utrack调试 艾肯icon_艾肯(iCON)Utrack声卡K歌设置图文教程
- mysql数据库命中率_Oracle数据库关于命中率的查询语句总结
- html中怎样写渐变色代码,纯css简单几行代码实现颜色渐变效果 非常漂亮
- 365天深度学习训练营-第P7周:咖啡豆识别
- 对数函数定义域和值域_对数函数的定义域、值域、定点
- 在线扫描php后门_解密php webshell后门
- 眼疾手快,真男人就来合成粽子三兄弟
- Curio for Mac(头脑风暴思维导图)