空指针异常我想是程序员见到比较多的异常啦,今天来探索的这个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
| public final class Optional<T> { private static final Optional<?> EMPTY = new Optional<>();
private final T value;
private Optional() { this.value = null; }
public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; }
private Optional(T value) { this.value = Objects.requireNonNull(value); }
public static <T> Optional<T> of(T value) { return new Optional<>(value); }
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value; }
public boolean isPresent() { return value != null; }
public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); }
public Optional<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : 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)); } }
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; }
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(); } }
@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); }
@Override public int hashCode() { return Objects.hashCode(value); }
@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<String> of = Optional.of(null); } }
|
isPresent
isPresent有两种作用:一个是判断是否有值,还有一个返回的是void,如果不为空的话执行Consumer消费型函数式代码。
1 2 3 4 5 6 7 8 9
| public class OptionalDemo { public static void main(String[] args) { Optional<String> val = Optional.ofNullable("yes"); System.out.println(val.isPresent());
val.ifPresent(s -> System.out.println(s.concat(" 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 filterOptional = optional.filter(param->param.contentEquals("Sean")); System.out.println(filterOptional); } }
|
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); } }
|