本文主要介绍Optional相关的API
Optional类介绍
一句话介绍Optional类:使用JDK8的Optional类来防止NPE(空指针异常)问题。
Optional类源码介绍
Optional的属性以及创建Optional容器的方法
// 1、创建出一个Optional容器,容器里边并没有装载着对象
private static final Optional<?> EMPTY = new Optional<>();
// 2、代表着容器中的对象
private final T value;
// 3、私有构造方法
private Optional() {
this.value = null;
}
// 4、得到一个Optional容器,Optional没有装载着对象
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
// 5、私有构造方法(带参数),参数就是具体的要装载的对象,如果传进来的对象为null,抛出异常
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// 5.1、如果传进来的对象为null,抛出异常
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
// 6、创建出Optional容器,并将对象(value)装载到Optional容器中。
// 传入的value如果为null,抛出异常(调用的是Optional(T value)方法)
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
// 创建出Optional容器,并将对象(value)装载到Optional容器中。
// 传入的value可以为null,如果为null,返回一个没有装载对象的Optional对象
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
所以可以得出创建Optional容器有三种方式:
- 调用empty()方法
// Optional的三种创建方式-empty
Optional<Object> empty = Optional.empty();
- 调用of()方法,传入的对象不可以为null,否则抛出NullPointerException
// Optional的三种创建方式-of
Optional<Object> o = Optional.of(new Object());
- 调用ofNullable()方法,传入的对象可以为null
// Optional的三种创建方式-ofNullable
Optional<Insurance> objectOptional = Optional.ofNullable(null);
Optional容器简单的方法
get方法
// 得到容器中的对象,如果为null就抛出异常
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
isPresent方法
// 判断容器中的对象是否为null
public boolean isPresent() {
return value != null;
}
orElse方法
// 如果容器中的对象存在,则返回。否则返回传递进来的参数
public T orElse(T other) {
return value != null ? value : other;
}
Optional容器进阶用法
ifPresent方法
//如果容器中的对象存在,则调用accept方法
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
orElseGet方法
// 如果对象存在,则直接返回,否则返回由Supplier接口的实现用来生成默认值
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
@FunctionalInterface
public interface Supplier<T> {
T get();
}
orElseThrow方法
// 如果存在,则返回。否则抛出supplier接口创建的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
filter方法
// 如果容器中的对象存在,并且符合过滤条件,返回装载对象的Optional容器,否则返回一个空的Optional容器
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
// 接口
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
map方法
// 如果容器的对象存在,则对其执行调用mapping函数得到返回值。然后创建包含mapping返回值的Optional,否则返回空Optional。
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));
}
}
// 接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Optional的总结
filter,map或flatMap一个函数,函数的参数拿到的值一定不是null。所以我们通过filter,map 和 flatMap之类的函数可以将其安全的进行变换,最后通过orElse系列,get,isPresent 和 ifPresent将其中的值提取出来。
其实吧,用Optional类也没有简化很多的代码,只是把NPE异常通过各种方法隐藏起来(包装了一层)。通过Lambda表达式可以让我们处理起来更加"优雅"一些。
使用Optional前后对比
到这里我们可以做一下和传统方式的对比
//传统判空
User userNull = null;
if(userNull != null){
System.out.println(userNull.getId());
}else{
System.out.println("UNKNOWN");
}
//使用Optional判空
Optional<User> userNull1 = Optional.ofNullable(userNull);
if(userNull1.isPresent()){
System.out.println(userNull.getId());
}else{
System.out.println("UNKNOWN");
}
//学会Optional和lambda方法后
Optional<User> userNull2 = Optional.ofNullable(userNull);
userNull2.map(user1 -> user1.getId()).orElse("UNKNOWN");
这里再使用3Y的代码做一下对比
public static void main(String[] args) {
User user = new User();
user.setName("Java3y");
System.out.println(test(user));
}
// 以前的代码v1
public static String test2(User user) {
if (user != null) {
String name = user.getName();
if (name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
}
// 以前的代码v2
public static String test3(User user) {
if (user != null && user.getName() != null) {
return user.getName().toUpperCase();
} else {
return null;
}
}
// 现在的代码
public static String test(User user) {
return Optional.ofNullable(user)
.map(user1 -> user1.getName())
.map(s -> s.toUpperCase()).orElse(null);
}
总结Optional类到此结束 , 有问题可以到3Y这里的博客看一下.
原文地址给女朋友讲解什么是Optional【JDK 8特性】