Java8新特性之——Optional类

一、简介

Optional类是Java 8中引入的一个用于处理null值的容器类。它封装了某个类型的值,这个值可以是null,也可以是非null,通过它可以更优雅和简洁地处理包含null值的对象。
Optional类的官方描述:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

翻译过来就是:

一个可能包含null值的容器对象。如果值存在,isPresent()方法将会返回true,get()方法将会返回该值。

二、特点

  1. Optional 类是一个容器类,用于保存可能为 null 的对象;
  2. Optional 实例提供了一些方法,能够更好地检测非空值以及在值为 null 的情况下提供替代值的方式;
  3. Optional 类是不可变的,即一旦创建了 Optional 实例,就不能改变该实例的值(除非初始化时的值为 null);
  4. Optional 类的最终目的是避免 NullPointerException 异常,从而提升代码的健壮性。

三、工厂方法

Optional的提供了三个工厂方法用于创建对象,empty( )、of( )、ofNullable( )

//构造一个空的Optional对象
Optional.empty();

//构造一个Optional对象,入参必须不会空,如果入参是空,就抛出空指针异常
Optional.of(T value);

//构造一个Optional对象,入参可以是空,如果入参是空,就返回Optional.empty()
Optional.ofNullable(T value);
  • empty():该方法返回null值的Optional对象
  • of():该方法返回指定非null值的Optional对象,如果传入的值为null,则会抛出NullPointerException异常。
  • ofNullable():该方法返回一个Optional对象,它可能包含指定的值,也可能为null。

3.1、empty()

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;
}

empty() 方法,将EMPTY赋值给一个新的 Optional 对象,EMPTY其实就是 new Optional<>(); 看私有构造方法 Optional(),其实就是把 value 设置成 null。

3.2、of()

//本方法
public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}

//Objects.requireNonNull
public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

of() 方法,就是调用的私有构造方法 Optional(T value),这个方法会调用 Objects.requireNonNull(value) ,这个方法会去判空,如果空就抛异常,非空就把对象返回。

3.3、ofNullable()

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

ofNullable() 方法,就是先判断 value 是否为空,如果是空的,就调用 empty() 方法,返回一个 value 为空的 Optional 对象,如果不为空,就调用 of() 方法返回一个 value 不为空的 Optional 对象。

四、常用方法

  • get():该方法获取 Optional 对象中包含的值。如果 Optional 对象为空,则会抛出 NoSuchElementException 异常。
  • isPresent():该方法检查 Optional 对象中是否包含非 null 的值,并返回 true 或 false。
  • ifPresent():如果 Optional 对象中的值存在,则会执行该参数实例的 accept 方法,并传入 Optional 中包含的值,否则不做任何操作。
  • orElse():该方法获取 Optional 对象中包含的值,如果该值为 null,则返回指定的默认值。
  • orElseGet():该方法获取 Optional 对象中包含的值,如果该值为 null,则返回一个由 Supplier 接口提供的默认值。
  • orElseThrow():该方法获取 Optional 对象中包含的值,如果该值为 null,则抛出指定的异常。
  • map(): 接受一个函数作为参数,在 Optional 对象中的值存在时,将其转换为另一种类型,然后返回一个包含这个类型值的新 Optional 对象。如果 Optional 对象为空,则会直接返回一个空的 Optional 对象。
  • flatMap(): 接受一个函数作为参数,但这里的函数返回值是一个 Optional 对象。如果 Optional 对象中的值存在,那么 flatMap() 方法会将其传递给函数作为参数,并且将函数的返回值包装在新的 Optional 对象中返回。如果 Optional 对象为空,那么直接返回一个空的 Optional 对象。
  • filter():该方法对 Optional 对象中包含的值进行过滤,并返回一个 Optional 对象。如果 Optional 对象为空或者过滤器不匹配,则直接返回一个空的 Optional 对象。

4.1、get()

public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

get() 方法很简单,就是返回包装的实际值,如果值是空,就抛出NoSuchElementException异常

Optional optional1 = Optional.of("hello world");
Optional optional2 = Optional.empty();
System.out.println(optional1.get());
System.out.println(optional2.get());

打印结果:

hello world
java.util.NoSuchElementException: No value present

4.2、isPresent()

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

isPresent() 方法用于判断包装对象的值是否非空。

Optional optional1 = Optional.of("hello world");
Optional optional2 = Optional.of("");
Optional optional3 = Optional.empty();
System.out.println(optional1.isPresent());
System.out.println(optional2.isPresent());
System.out.println(optional3.isPresent());

打印结果:

true
true
false

4.3、ifPresent()

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

ifPresent() 方法用于如果的值存在,则会执行 consumer 的 accept 方法,并传入value,否则不做任何操作。

User user = new User();
String name = "zhangsan";
Optional.ofNullable(name).ifPresent(user::setName);
System.out.println(user);

打印结果:

User{name=‘zhangsan’}

4.4、orElse()

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

orElse() 方法用于如果获取value,如果 value 为空,返回传入的默认值。

Optional optional1 = Optional.of("hello world");
Optional optional2 = Optional.ofNullable(null);
System.out.println(optional1.orElse("hello java"));
System.out.println(optional2.orElse("hello java"));

打印结果:

hello world
hello java

4.5、orElseGet()

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

orElseGet() 方法用于获取 value,如果 value 为空,返回一个由 Supplier 接口提供的默认值。

Optional<String> optional1 = Optional.of("hello world");
Optional<String> optional2 = Optional.ofNullable(null);
System.out.println(optional1.orElseGet(() -> "hello java"));
System.out.println(optional2.orElseGet(() -> "hello java"));

打印结果:

hello world
hello java

4.6、orElseThrow()

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

orElseThrow() 方法获取 value,如果 value 为空,则抛出指定的异常

Optional<String> optional1 = Optional.of("hello world");
Optional<String> optional2 = Optional.ofNullable(null);
System.out.println(optional1.orElseThrow(() -> new IllegalStateException("can't get value")));
System.out.println(optional2.orElseThrow(() -> new IllegalStateException("can't get value")));

打印结果:

hello world
java.lang.IllegalStateException: can’t get value

4.7、map()

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));
    }
}

map() 方法对 Optional 对象中包含的值进行转换,并返回一个新的 Optional 对象。如果 Optional 对象为空,则直接返回一个空的 Optional 对象。

User user = new User();
user.setName("zhangsan");
Optional<String> nameOptional = Optional.ofNullable(user).map(u -> u.getName());
System.out.println(nameOptional.orElse(null));

打印结果:

zhangsan

4.8、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));
    }
}

flatMap() 方法和 map() 方法类似, 区别在于 flatMap() 方法的函数返回值是一个 Optional 对象,而 map() 方法的函数返回值是一个普通类型。

User user = new User();
user.setName("zhangsan");
Optional<String> nameOptional = Optional.ofNullable(user).flatMap(u -> Optional.ofNullable(user.getName()));
System.out.println(nameOptional.orElse(null));

打印结果:

zhangsan

4.9、filter()

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

filter() 方法通过传递一个Predicate(断言函数)来对Optional对象中的元素进行过滤。如果Optional对象中的值存在,filter方法会将其传递给断言函数进行判断。如果该元素符合断言函数的要求,则返回一个包含该元素的Optional对象。否则,返回空的Optional对象。

User user = new User();
user.setAge(20);
Optional.ofNullable(user).filter( u -> u.getAge() > 18).ifPresent(u ->  System.out.println("The user age is more than 18."));

打印结果:

The user age is more than 18.

五、意义

Optional 的意义在于:

  1. 避免空指针异常:使用 Optional 可以将可能为 null 的值包装起来,从而避免在调用时出现空指针异常的情况。
  2. 使代码更加清晰和可读:使用Optional可以明确表达某个值可能不存在的情况,使代码更加清晰和可读性更强。
  3. 鼓励更好的编程习惯:使用Optional可以鼓励开发者更加关注可能的null值,使得开发者更加倾向于编写更健壮、更易于维护的代码。

你可能感兴趣的:(Java,源码学习,java)