读Java实战(第二版)笔记07_用Optional取代null

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方法

读Java实战(第二版)笔记07_用Optional取代null

发表回复