java8系列-05 Optional

空指针异常我想是程序员见到比较多的异常啦,今天来探索的这个Optional工具类就是来处理这类问题的。用过Google Guava(后期应该会出一个系列,请持续关注)的都应该知道,Guava这套工具类库里面也有一个Optional,而且作用和今天来探索的这个java新特性是一样的。既然又是探索,那我们先打开idea,然后ctrl+鼠标左键进到optional的世界看一下吧。

源码片段

接下来我将逐行解释一下源码(像我这样给jdk源码这样加注释的怕是很少了^_^)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// final修饰说明此类是无法被引用的哈
public final class Optional<T> {
// 这个是EMPTY的实例
private static final Optional<?> EMPTY = new Optional<>();

// 如果非空,则为该值;如果为空,则表示不存在任何值。
private final T value;

// 构造私有看来此类也不能被new
private Optional() {
this.value = null;
}

// 返回一个空的实例,@SuppressWarnings不提醒警告
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}

// 根据value来构造出一个实例
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}

// 返回一个带有value的optional,注意value如果为空则会报空指针异常
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}

// 和上面一样,但是这里value为空不会有空指针异常
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}

// 如果当前有值则返回当前值,否则抛出NoSuchElementException
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}

// 如果这个Optional是存在的则返回true,否则为false
public boolean isPresent() {
return value != null;
}

// 如果option对象保存的值不是null,则调用consumer对象,否则不调用
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}

// 判断Optional对象中保存的值是否满足Predicate,并返回新的Optional。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}

// 如果value不为null,则进行函数运算,返回一个新的Optional,否则返回empty
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}

// 上一章讲到过Stream里面的flatMap,就是对一个大的集合进行一个扁平化的操作。
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}

// 不解释
public T orElse(T other) {
return value != null ? value : other;
}

// 怎么办?也不想解释,关于Supplier供给者函数式的作用麻烦翻到此系列的第二章
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}

// 重写了Object的方法
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}

if (!(obj instanceof Optional)) {
return false;
}

Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
}

// 重写了Object的方法
@Override
public int hashCode() {
return Objects.hashCode(value);
}

// 如果值不为空则返回Optional[value],否则Optional.empty。认真看过我上一章的也许还能记忆起来
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}

优雅食用

这里捡几个比较常用的在这里列出来吧

of && ofNullable

上面注释有提到,这两个都是被用来创建Optional对象。区别在于ofNullable还判空了。这就造成了ofNullable的实用性比of要高那么一丢丢。下面来看一个例子吧~

1
2
3
4
5
6
7
8
public class OptionalDemo {
public static void main(String[] args) {
Optional<String> ofNullable = Optional.ofNullable(null);
System.out.println(ofNullable);// Optional.empty

Optional<String> of = Optional.of(null); // 代码执行到这里会抛出NullPointerException
}
}

isPresent

isPresent有两种作用:一个是判断是否有值,还有一个返回的是void,如果不为空的话执行Consumer消费型函数式代码。

1
2
3
4
5
6
7
8
9
public class OptionalDemo {
public static void main(String[] args) {
// 先创建一个Optional
Optional<String> val = Optional.ofNullable("yes");
System.out.println(val.isPresent()); // true

val.ifPresent(s -> System.out.println(s.concat(" or no?"))); // yes or no?
}
}

filter && map

直接看例子最好啦

1
2
3
4
5
6
7
8
9
10
public class OptionalDemo {
public static void main(String[] args) {
Optional<String> optional = Optional.ofNullable("code666");
Optional<String> newOptional = optional.map(param->param.concat(".top"));
System.out.println(newOptional); // Optional[code666.top]

Optional filterOptional = optional.filter(param->param.contentEquals("Sean")); // 如果条件成立的话会返回Optional[code666]
System.out.println(filterOptional); // Optional.empty
}
}

orElse && orElseGet

长得虽然差不多,orElseGet还带了一个Supplier供给者函数看着高大上一点,其实也差不多。记得在第二章有说过,供给者函数就有点像工厂的味道而已。

1
2
3
4
5
6
7
8
9
public class OptionalDemo {
public static void main(String[] args) {
String res = (String) Optional.ofNullable(null).orElse("这个结果为空");
System.out.println(res); // 这个结果为空

String res2 = (String) Optional.ofNullable(null).orElseGet(()-> "The result is empty.");
System.out.println(res2); // The result is empty.
}
}

java8系列-05 Optional
https://code666.top/articles/2019/03/07/1551973192759.html
作者
Sean
发布于
2019年3月7日
许可协议