读Java实战(第二版)笔记07_用Optional取代null
2023-03-31 10:38:39 时间
1. null的由来
1.1. 历史上被引入到程序设计语言中,目的是为了表示变量值的缺失
1.2. 包括Java在内的大多数现代程序设计语言为了与更老的语言保持兼容
2. null带来的问题
2.1. 错误之源
2.1.1. NullPointerException是最典型的异常
2.2. 代码膨胀
2.2.1. 深度嵌套的null检查
2.3. 自身毫无意义
2.3.1. 自身没有任何的语义
2.3.2. 以一种错误的方式对缺失变量值的建模
2.4. 破坏了Java的哲学
2.4.1. 让程序员意识到指针的存在
2.4.2. null指针
2.5. 在类型系统上开了个口子
2.5.1. null并不属于任何类型
2.5.2. null可被赋值给任意引用类型的变量
3. 防御式检查NullPointerException
3.1. 深层质疑
3.1.1. 每次你不确定一个变量是否为null时,都需要添加一个进一步嵌套的if块,这也增加了代码缩进的层数
3.2. 过多的退出语句
3.2.1. 为了避免深层递归的if语句块
3.2.2. 但这种流程是极易出错的
4. null的替代品
4.1. Groovy
4.1.1. 安全导航操作符(safe navigation operator,标记为?)
4.1.2. 可以安全访问可能为null的变量
4.1.3. 掩耳盗铃
4.2. Haskell
4.2.1. Maybe类型
4.2.1.1. 对Optional值的封装
4.2.1.2. 可以是指定类型的值
4.2.1.3. 可以什么都不是
4.3. Scala
4.3.1. Option[T]
4.3.1.1. 显式地调用Option类型的available操作,检查该变量是否有值
4.3.1.1.1. 变相的“null检查”
4.3.1.1.2. 类型系统默认会强制进行检查
4.3.1.2. 可以包含类型为T的变量
4.3.1.3. 可以不包含该变量
4.4. Java
5. java.util.Optional
5.1. 封装Optional值的类
5.1.1. 对存在或缺失的变量值进行建模
5.1.2. 用户只需要阅读方法签名,就能了解该方法是否接受一个Optional类型的值
5.1.3. 不再需要为其添加null的检查
5.1.3.1. 因为null的检查只会掩盖问题,并未真正地修复问题
5.2. 清晰界定变量值缺失原因
5.2.1. 结构上的问题
5.2.2. 算法上的缺陷
5.2.3. 数据中的问题
5.3. 设计初衷仅仅是要支持能返回Optional对象的语法
5.3.1. 没特别考虑将其作为类的字段使用
5.3.2. 并未实现Serializable接口
5.3.2.1. 替代方案提供一个能访问声明为Optional、变量值可能缺失的接口
5.4. Optional.empty
5.4.1. 声明一个空的Optional
5.4.2. 变量不存在时返回Optional类的特定单一实例
5.5. Optional.of
5.5.1. 依据一个非空值创建Optional
5.6. Optional.ofNullable
5.6.1. 可接受null的Optional
5.6.2. 创建一个允许null值的Optional对象
5.7. get()
5.7.1. 最简单但又最不安全的方法
5.7.2. 抛出一个NoSuchElementException异常
5.8. orElseThrow(Supplier<? extends="" x=""? > exceptionSupplier)
5.8.1. 类似get方法
5.8.2. 定制希望抛出的异常类型
5.9. orElse(T other)
5.9.1. Optional对象不包含值时提供一个默认值
5.10. orElseGet(Supplier<? extends="" t=""? > other)
5.10.1. orElse方法的延迟调用版
5.10.2. Supplier方法只有在Optional对象不含值时才执行调用
5.10.3. 应用场景
5.10.3.1. 创建默认值是件耗时费力的工作,借此提升程序的性能
5.10.3.2. 非常确定某个方法仅在Optional为空时才进行调用
5.11. or(Supplier<? extends=""? ><? extends="" t=""? >> supplier)
5.11.1. Java9
5.11.2. 类似orElseGet方法
5.11.3. 不会解包Optional对象中的值,即便该值是存在的
5.12. ifPresent(Consumer<? super="" t=""? >consumer)
5.12.1. 变量值存在时,执行一个以参数形式传入的方法
5.12.2. 变量值不存在时,就不进行任何操作
5.13. ifPresentOrElse(Consumer<? super="" t=""? > action, Runnable emptyAction)
5.13.1. Java9
5.13.2. 接受一个Runnable方法,如果Optional对象为空,就执行该方法所定义的动作
5.14. 和Stream接口的相似之处
5.14.1. map方法
5.14.1.1. 使用map从Optional对象中提取和转换值
5.14.2. flatMap方法
5.14.2.1. 使用flatMap链接Optional对象
5.14.3. filter方法
5.14.3.1. 使用filter剔除特定的值
5.15. 操纵由Optional对象构成的Stream
5.15.1. Java9
5.15.2. 把一个含值的Optional对象转换成由该值构成的Stream对象
5.15.3. 把一个空的Optional对象转换成等价的空Stream
5.16. 基础类型的Optional对象
5.16.1. OptionalInt
5.16.2. OptionalLong
5.16.3. OptionalDouble
5.16.4. 不推荐
5.16.4.1. Optional对象最多只包含一个值
5.16.4.2. 基础类型的Optional不支持map、flatMap以及filter方法
相关文章
- 《漫谈 MQ》设计 MQ 的 3 个难点
- Java开发日常
- 手把手教你提交Jar包到Maven公共仓库 | 萌新写开源02
- 一次完整的JVM堆外内存泄漏故障排查记录
- elasticsearch之自定义Java代码的安全策略管理
- Java中的受检异常
- 并发编程之对象的发布和逸出
- 并发编程之内存可见性
- 并发编程之线程安全性
- 并发编程的几种形式
- 并发编程简介
- 使用Ant自动化我们的java项目生成
- Java构建工具Ant小记(一)
- 打造Ubuntu下Java开发环境
- 【从零开始撸一个App】Kotlin
- Jenkins 集成postman 自动化运行接口测试用例
- 高并发下限流(学习笔记)
- jenkins 构建后发送钉钉消息通知(插件)
- ant+Jacoco 统计tomcat远程部署后项目接口自动化测试或者功能测试代码覆盖率
- jmeter测试java代码