Java 8中 Optional 类源码实现与分析
Posted 然笑后端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 8中 Optional 类源码实现与分析相关的知识,希望对你有一定的参考价值。
Optional
类位于 java.util
包下,自 JDK 1.8 版本新增的,它是一个 final 类,不能被继承,且构造函数是 private 的,不能被实例化,它提供了一系列对 null 空值的处理方法,是一个包装类,既可以包装非空对象,也可以包装空值,下面来看看它的定义以及默认构造函数。
public final class Optional<T>
private Optional()
this.value = null;
众所周知,在Java开发过程中,经常需要对 null
进行判断和处理,如果漏掉了,就会引发 NullPointerException
异常,因此 null
判断几乎会遍布在代码的每个角落,那么神奇的 null
是如何诞生的呢?
其实,null
引入的目的是为了表示变量值的缺失。
那么在Java 8 中为什么会引入这样的一个 Optional
类呢?主要是为了对存在或缺失的变量值建模,这样一来,不管变量有没有值,都可以统一使用 Optional
来表示,它可以减少 null
值的判断逻辑,使得代码结构更加简单,同时也可以减少 NullPointerException
异常的出现。
1、构造函数
Optional
类提供了两个构造函数,都是 private
的,如下:
private Optional()
this.value = null;
private Optional(T value)
// value 值不能为 null,否则会抛出空指针异常
this.value = Objects.requireNonNull(value);
因为构造函数是私有的,所以不能直接实例化 Optional
类,那么如果创建 Optional
实例呢?可以通过以下的三个方法:
empty()
:通过静态工厂方法创建一个空的Optional
实例;of()
:将指定值用Optional
封装之后返回,如果该值为null
,则抛出一个NullPointerException
异常;ofNullable()
:将指定值用Optional
封装之后返回,如果该值为null
,则返回一个空的Optional
对象;
2、方法
Optional
类提供了一些方法,主要分为 静态方法和实例方法,像上面提到的三个方法,都是静态方法,主要用于创建 Optional
实例。
2.1 静态方法
(1)empty()
empty()
方法是通过静态工厂方法创建一个空的 Optional
实例,不包含任何值,其定义如下:
private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty()
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
如果直接调用 empty()
方法,将会直接返回静态常量 EMPTY
.
(2)of()
of()
方法将指定值用 Optional
封装之后返回,如果该值为 null
,则抛出一个 NullPointerException
异常,其源码如下:
public static <T> Optional<T> of(T value)
return new Optional<>(value);
直接是通过 new Optional(T value)
方法创建实例,该构造方法使用 Objects.requireNonNull()
对传入的参数进行检查,其源码如下:
public static <T> T requireNonNull(T obj)
if (obj == null)
throw new NullPointerException();
return obj;
也就是说 of()
方法不接受 null
空值。
(3)ofNullable()
ofNullable()
方法将指定值用 Optional
封装之后返回,如果该值为 null
,则返回一个空的 Optional
对象,其定义如下:
public static <T> Optional<T> ofNullable(T value)
return value == null ? empty() : of(value);
从实现可以看出,ofNullable()
方法可以接受 null
空值,而 of()
方法不能接收空值,这也是它与 of()
方法之间的区别。
2.2 实例方法
(1)get()
get()
方法是用来获取 Optional
封装的值的,如果该值存在,将该值用 Optional
封装返回,否则抛出一个 NoSuchElementException
异常,其定义如下:
public T get()
if (value == null)
throw new NoSuchElementException("No value present");
return value;
其中的 value
值是 Optional
中的成员变量,其定义如下:
private final T value;
(2)isPresent()
isPresent()
方法用于判断 value
值是否存在,如果值存在就返回true,否则返回false,其定义如下:
public boolean isPresent()
return value != null;
(3)ifPresent()
ifPresent()
方法也是用于判断 value
值是否存在,如果值存在,就执行使用该值的方法调用,否则什么也不做,其定义如下:
public void ifPresent(Consumer<? super T> consumer)
if (value != null)
consumer.accept(value);
该方法的参数是 Consumer
,如果 value
值存在,则会传入到 Consumer.accept()
方法中,其中 Consumer
类是一个功能性接口,其定义如下:
@FunctionalInterface
public interface Consumer<T>
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after)
Objects.requireNonNull(after);
return (T t) -> accept(t); after.accept(t); ;
(4)filter()
filter()
方法主要用于条件过滤,如果值存在并且满足提供的谓词,就返回包含该值的 Optional
对象;否则返回一个空的 Optional
对象,其定义如下:
public Optional<T> filter(Predicate<? super T> predicate)
// filter 方法中的谓词参数不能为空,否则会抛出空指针异常
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
filter()
方法的参数是需要传入一个 Predicate
谓词,并且参数不能为 null
,否则会抛出 NullPointerException
异常,当 value
值存在时,会调用 Predicate.test()
方法进行判断。
(5)map()
map()
方法主要是对 Optional
封装的值执行 mapping
函数,如果值存在,就对该值执行提供的mapping函数调用,如果值不存在,则直接返回空的 Optional
对象,其定义如下:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
// map 方法中的参数 mapper 函数不能为空,否则会抛出空指针异常
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else
return Optional.ofNullable(mapper.apply(value));
(6)flatMap()
flatMap()
方法主要也是对 Optional
封装的值执行 mapping
函数,如果值存在,就对该值执行提供的mapping函数调用,返回一个Optional
类型的值,否则就返回一个空的 Optional
对象,其定义如下:
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
// flatMap 方法中的参数 mapper 函数不能为空,否则会抛出空指针异常
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else
return Objects.requireNonNull(mapper.apply(value));
flatMap()
方法和 map()
方法有什么区别呢?从方法定义的参数
(7)orElse()
orElse()
方法主要用于如果有值,直接返回,如果没有值时,则返回该方法设置的默认值,其源码如下:
public T orElse(T other)
return value != null ? value : other;
(8)orElseGet()
orElseGet()
方法和 orElse()
方法的作用类似,只是当没有值时, orElseGet()
方法不是直接返回一个值,而是一个由指定的 Supplier
接口返回的值,其定义如下:
public T orElseGet(Supplier<? extends T> other)
return value != null ? value : other.get();
(9)orElseThrow()
orElseThrow()
方法用于如果有值,则直接返回,如果没有值,则直接抛出一个由指定的 Supplier
接口生成的异常,其定义如下:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
// 如果值不为 null,直接返回
if (value != null)
return value;
else
throw exceptionSupplier.get();
3、其他相关类
除了 Optional
类外,java.util
包下还提供了另外的三个基础类型的 Optional
类,如下:
OptionalInt
:用于包装整型类;OptionalLong
:用于包装长整型类;OptionalDouble
:用于包装Double类型;
这三个类的源码与 Optional
类似,只是 Optional
类使用了泛型定义,而它们只能应用于基础数据类型。
以上是关于Java 8中 Optional 类源码实现与分析的主要内容,如果未能解决你的问题,请参考以下文章