每一秒钟的时间都值得铭记

0%

JDK8新特性之Optional类

什么是 Optional 类?

Optional 是 JDK8 新增加的一个工具类,位于 java.util 包下。

Optional 类是一个可以为 null 的容器对象。如果值存在则 isPresent() 方法会返回 true,调用 get() 方法会返回该对象。

Optional 是个容器:它可以保存类型 T 的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常(微笑)。

Optional 类的方法及使用

Optional 类中提供了一些常用的方法,同时结合 JDK8 的 Lambda 新特性使用,能够更加方便。

私有构造

1
2
3
private Optional() {
this.value = null;
}

在 Optional 类中,构造函数被私有访问修饰符修饰,也就意味着我们无法使用 new 关键字来创建对象。

empty()

1
2
3
Optional<User> empty = Optional.empty();
System.out.println(empty != null);
System.out.println(empty);

使用 Optional 类的静态方法 empty() ,可以创建一个容器内值为 nullOptional 对象。使用该方法,得到的 Optional 类是存在的,只不过该类中的值为 null

源码:

1
2
3
4
5
6
7
private static final Optional<?> EMPTY = new Optional<>();

public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}

of(T value)

1
2
3
4
User user1 = new User();
Optional<User> optionalUser1 = Optional.of(user1);
User user2 = null;
Optional<User> optionalUser2 = Optional.of(user2);

of(T value) 方法是 Optional 类创建容器的主要方法,使用该方法,可以创建一个泛型为 TOptional 容器,并向容器内注入一个值对象。

需要注意的是,使用 of(T value) 方法,参数不可以为 null,否则程序会报空指针异常。

源码:

1
2
3
4
5
6
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
1
2
3
4
5
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}

ofNullable(T value)

1
2
3
4
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
User user2 = null;
Optional<User> optionalUser2 = Optional.ofNullable(user2);

ofNullable(T value) 方法和 of(T value) 方法唯一的区别在于,参数可以为 null,如果参数为 null,会调用 empty() 方法返回一个空的 Optional 对象。

源码:

1
2
3
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}

get()

1
2
3
4
5
6
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
optionalUser1.get();
User user2 = null;
Optional<User> optionalUser2 = Optional.ofNullable(user2);
optionalUser2.get();

get() 方法,用于返回 Optional 容器中的值对象。但是如果 Optional 容器为一个空容器,即内部的值为 null,则会抛出 NoSuchElementException 异常。

源码:

1
2
3
4
5
6
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}

isPresent()

1
2
3
4
5
6
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
System.out.println(optionalUser1.isPresent());
User user2 = null;
Optional<User> optionalUser2 = Optional.ofNullable(user2);
System.out.println(optionalUser2.isPresent());

isPresent() 方法,用于判断 Optional 容器内是否有值,有则返回 true,否则返回 false

源码:

1
2
3
public boolean isPresent() {
return value != null;
}

ifPresent(Consumer<? super T> consumer)

1
2
3
4
5
6
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
optionalUser1.ifPresent((o) -> System.out.println(o));
User user2 = null;
Optional<User> optionalUser2 = Optional.ofNullable(user2);
optionalUser2.ifPresent((o) -> System.out.println(o));

ifPresent(Consumer<? super T> consumer) 方法,参数是一个消费型函数式接口,可以配合 Lambda 表达式使用。
该方法的作用为:如果 Optional 容器中有值,则执行 Consumer 接口中的方法,否则不做其他任何操作。

源码:

1
2
3
4
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}

filter(Predicate<? super T> predicate)

1
2
3
4
5
6
7
8
9
User user1 = new User();
user1.setUsername("zhangsan");
Optional<User> optionalUser1 = Optional.ofNullable(user1);
System.out.println(optionalUser1.filter((o) -> o.getUsername().equals("zhangsan")));;

User user2 = new User();
user2.setUsername("lisi");
Optional<User> optionalUser2 = Optional.ofNullable(user2);
System.out.println(optionalUser2.filter((o) -> o.getUsername().equals("zhangsan")));;

filter(Predicate<? super T> predicate) 方法用于过滤 Optional 容器中的值,如果 容器内的值符合 Predicate 函数所定义的接口,即返回 true,则返回原来的 Optional 对象,否则返回空的 Optional 容器对象。

源码:

1
2
3
4
5
6
7
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}

map(Function<? super T, ? extends U> mapper)

1
2
3
4
User user1 = new User();
user1.setUsername("zhangsan");
Optional<User> optionalUser1 = Optional.ofNullable(user1);
System.out.println(optionalUser1.map((o) -> o.getUsername()).get());

map(Function<? super T, ? extends U> mapper) 方法,可以将 Optional 容器内的值替换为其他类型的值,具体的替换规则由 Function 函数定义。
例如上面的代码中,将 User 类型的 Optional 容器替换为了 String 类型的 Optional 容器。

源码:

1
2
3
4
5
6
7
8
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));
}
}

flatMap(Function<? super T, Optional> mapper)

1
2
3
4
User user1 = new User();
user1.setUsername("zhangsan");
Optional<User> optionalUser1 = Optional.ofNullable(user1);
System.out.println(optionalUser1.flatMap((o) -> Optional.ofNullable(o.getUsername())).get());

该方法与 map(Function<? super T, ? extends U> mapper) 方法类似,不过该方法要求在 Function 函数中返回 Optional 对象,并且返回的 Optional 对象不允许为 null

源码:

1
2
3
4
5
6
7
8
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));
}
}

orElse(T other)

1
2
3
4
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
User user2 = optionalUser1.orElse(new User());
System.out.println(user1 == user2);

orElse(T other) 方法和 get() 方法类似,不过比 get() 方法多了一层保险机制,如果 Optional 容器中的值为 null,则会返回 orElse(T other) 方法参数中的对象,该参数类型必须和 Optional 泛型类型一致。

源码:

1
2
3
public T orElse(T other) {
return value != null ? value : other;
}

orElseGet(Supplier<? extends T> other)

1
2
3
4
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
User user2 = optionalUser1.orElseGet(() -> new User());
System.out.println(user1 == user2);

该方法和功能类似,不过和 orElse(T other) 方法不同的是, Optional 容器中的值为 null时返回的对象通过生产型函数接口来创建并返回。

源码:

1
2
3
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}

orElseThrow(Supplier<? extends X> exceptionSupplier)

1
2
3
4
User user1 = new User();
Optional<User> optionalUser1 = Optional.ofNullable(user1);
User user2 = optionalUser1.orElseThrow(() -> new Exception("抛出异常信息"));
System.out.println(user1 == user2);

该方法的逻辑和 orElse(T other)orElseGet(Supplier<? extends T> other) 基本类似,不过当 Optional 容器的值为 null 时,会抛出生产型函数返回的异常对象。

源码:

1
2
3
4
5
6
7
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}

其他方法

Optional 类除了上述的特有方法之外,还重写了 equals()hashCode()toString() 等通用方法,在本篇文章中不做过多的讲述。

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------这是我的底线^_^-------------