网站首页 > java教程 正文
1、Optional类概述
1.1、Optional类介绍
Optional类是Java 8 才引入的,Optional 是个容器,它可以保存类型 T 的值,或者仅仅保存 null。Optional 提供了很多方法,这样我们就不用显式进行空值检测。Optional 类的引入很好的解决空指针异常。
Java 8 引入 Optional 类,用来解决 NullPointerException。 Optional 代替 if…else 解决空指针问题,使代码更加简洁。
1.2、Java8之前的空指针异常判断
Java 在使用对象过程中,访问任何方法或属性都可能导致 NullPointerException:
例如我们通过以下方法,获取存在 student 对象中的 Age 值。
在这样的示例中,如果我们想要避免由 student 或 student.age 为空而导致的空指针问题,我们就需要采用防御式检查减少 NullPointerException(在访问每一个值之前对其进行明确地检查):
然而,这种方案并不是很理想,因为为此会多出多个不同的退出点(return),使得代码维护变得艰难,之后每个可能的 null 检查都会新增一个退出点。
为了简化这个过程,我们来看看用 Optional 类是怎么做的。
1.3、Java8之后Optional的使用
当需要判断的量多时,此时的这些判断语句可能会导致代码臃肿冗余,为此 Java8 特意推出了 Optional 类来帮助我们去处理空指针异常。
下面是 Optional 的一些基本用法:
2、Optional类使用
2.1、Optional类常用方法总结
2.2、Optional对象创建
2.2.1、Optional.empty()方法
使用 Optional.empty() 方法声明一个空的 Optional:
2.2.2、Optional.of(T t)方法
使用 Optional.of(T t) 方法创建一个包含非空值的 Optional 对象 (不推荐):
如果 student 为 null,这段代码会立即抛出一个 NullPointerException,而不是等到访问 student 的属性值时才返回一个错误。
2.2.3、Optional.ofNullable(T t)方法
使用 Optional.ofNullable(T t) 方法创建一个包含可能为空的值的 Optional 对象 (推荐):
2.3、Optional对象获取
2.3.1、get()方法
get() 方法,如果变量存在,它直接返回封装的变量值,否则就抛出一个 NoSuchElementException 异常,不推荐使用:
optional.map(Student::getAge).get()
2.3.2、orElse(T other)方法
orElse(T other) 方法,它允许你在 Optional 对象不包含值时提供一个默认值:
optional.map(Student::getAge).orElse(20));
2.3.3、orElseGet(Supplier<? extends T> other)方法
orElseGet(Supplier<? extends T> other) 方法,它是 orElse 方法的延迟调用版,Supplier 方法只有在 Optional 对象不含值时才执行调用(懒加载):
optional.map(Student::getAge).orElseGet(() -> Integer.MAX_VALUE);
2.3.4、orElseThrow(Supplier<? extends X> exceptionSupplier)方法
orElseThrow(Supplier<? extends X> exceptionSupplier) 方法,它和 get 方法非常类似,它们遭遇 Optional 对象为空时都会抛出一个异常,但是使用 orElseThrow 可以定制希望抛出的异常类型:
optional.orElseThrow(() -> new RuntimeException("student不存在!"));
2.3.5、ifPresent(Consumer<? super T> consumer)方法
ifPresent(Consumer<? super T> consumer) 方法,它让能在变量值存在时执行一个作为参数传入的方法,否则就不进行任何操作:
optional.ifPresent(o -> o.setAge(18));
2.4、Optional对象中值的提取和转换
2.4.1、map()方法
map() 方法,如果值存在,就对该值执行提供的 mapping 函数调用,如果值不存在,则返回一个空的 Optional 对象。
引入 Optional 以前:
引入 Optional 以后:
Optional 的 map 方法和 Java 8 中 Stream 的 map 方法相差无几。
2.4.2、flatMap()方法
flatMap() 方法,对于嵌套式的 Optional 结构,我们应该使用 flatMap 方法,将两层的 Optional 合并成一个。
我们试着重构以下代码:
由于我们刚刚学习了如何使用 map,我们的第一反应可能是我们可以利用 map 重写之前的代码:
不幸的是,这段代码无法通过编译。为什么呢? optPerson 是 Optional<Person> 类型的 变量, 调用 map 方法应该没有问题。但 getCar 返回的是一个 Optional<Car> 类型的对象,这意味着 map 操作的结果是一个 Optional<Optional<Car>> 类型的对象。因此,它对 getInsurance 的调用是非法的。
下面应用 map 和 flatMap 对上述示例进行重写:
2.5、Optional对象其他方法
2.5.1、isPresent()方法
可以使用 isPresent() 方法检查 Optional 对象是否包含非空值,例如:
2.5.2、filter()方法
filter() 方法接受一个谓词作为参数。如果 Optional 对象的值存在,并且它符合谓词的条件,filter 方法就返回其值,否则它就返回一个空的 Optional 对象。
比如,你可能需要检查保险公司的名称是否为 “Cambridge-Insurance”。
使用 Optional 对象的 filter 方法,这段代码可以重构如下:
3、Optional注意事项
3.1、Optional的序列化问题
由于 Optiona l类设计时就没特别考虑将其作为类的字段使用,所以它也并未实现 Serializable 接口。由于这个原因,如果你的应用使用了某些要求序列化的库或者框架,在域模型中使用Optional,有可能引发应用程序故障。
然而,我们相信,通过前面的介绍,我们已经看到用 Optional 声明域模型中的某些类型是个不错的主意,尤其是你需要遍历有可能全部或部分为空,或者可能不存在的对象时。如果你一定要实现序列化的域模型,作为替代方案, 我们建议你像下面这个例子那样,提供一个能访问声明为 Optional、变量值可能缺失的接口,代码清单如下:
3.2、避免使用基础类型的 Optional 对象
Optional 提供了的一些基础类型 —— OptionalInt、OptionalLong 以及 OptionalDouble ,但不推荐大家使用基础类型的 Optional,因为基础类型的 Optional 不支持 map、 flatMap 以及 filter 方法,而这些却是 Optional 类常用的方法。可以使用 Optional<Int>, Optional<Long>, Optional<Double> 等替代。3. orElse方法的使用
3.3、orElse方法的使用
orElse 中调用的方法一直都会被执行,orElseGet 方法只有在 Optional 对象不含值时才会被调用,所以使用 orElse 方法时需要谨慎, 以免误执行某些不被预期的操作。此种情况下,可使用 orElseGet 方法代替它。
猜你喜欢
- 2025-07-03 一天一道Java面试题,坚持三个月,菜鸟变大佬(JVM篇)
- 2025-07-03 Java任务调度器的构建:打造高效的任务管理大师
- 2025-07-03 完整实现-通过DelayQueue实现延时任务
- 2025-07-03 Java并发工具:DelayQueue(java 并发工具)
- 2025-07-03 别再被“Java过时论”忽悠了!它只是换了个方式“潮”起来。
- 2025-07-03 Java应用卡顿?JProfiler:给你一双透视眼,秒变性能优化高手!
- 2025-07-03 盘点Java中最没用的知识③:这3个“过气王者”你还在当宝贝用?
- 2025-07-03 JVM 性能调优,实现高吞吐量和低延迟
- 2025-07-03 Java中ScheduledExecutorService的高效使用技巧
- 2025-07-03 如何实现延迟队列(延迟队列怎么实现)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)