空指针异常我想是程序员见到比较多的异常啦,今天来探索的这个Optional工具类就是来处理这类问题的。用过Google Guava(后期应该会出一个系列,请持续关注)的都应该知道,Guava这套工具类库里面也有一个Optional,而且作用和今天来探索的这个java新特性是一样的。既然又是探索,那我们先打开idea,然后ctrl+鼠标左键进到optional的世界看一下吧。
接下来我将逐行解释一下源码(像我这样给jdk源码这样加注释的怕是很少了_)
// 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要高那么一丢丢。下面来看一个例子吧~
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消费型函数式代码。
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
直接看例子最好啦
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供给者函数看着高大上一点,其实也差不多。记得在第二章有说过,供给者函数就有点像工厂的味道而已。
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.
}
}