Optional详解

发布时间 2023-08-18 18:24:47作者: _mcj

1.介绍

Optional是Java8引入的一个新的类,它是java.util包下面的一个类。主要目的是为了解决空指针异常问题,它既可以含有对象也可以为空。

2.Optional的使用

2.1:创建一个Optional
如果需要创建一个空的Optional的话,则可以使用Optional的empty()方法。empty方法的代码为:

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

该方法的作用就是返回个空对象,样例代码:

Optional<Object> empty = Optional.empty();
System.out.println(empty.get());

输出结果:
image
可以看出其是没有值得,所以报了个异常,这个异常是get方法进行判断与抛出的。
如果要创建的对象可以明确的确认该对象不为null,那么可以使用Optional的of()方法,但是需要注意的是对象为null是该方法会报一个空指针异常。of的源码为:

public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

样例代码为:

System.out.println(Optional.of("5"));
System.out.println(Optional.of(null));

输出结果为:
image
可以从输出结果看出值不为null时则会创建一个有值的实例对象,如果值为null时则会抛出一个空指针异常。
如果要创建的对象不能够确定是否为null的话,则可以使用Optional的ofNullable()方法,这个方法会根据传入的值是否为null来返回实例对象,如果为null的话,则会返回empty(),不为null的话,则会调用of()方法创建实例。其源码为:

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

样例代码如下:

System.out.println(Optional.ofNullable("5"));
System.out.println(Optional.ofNullable(null));

运行结果为:
image
从结果可以看出,当值为null时,ofNullable()方法并不会提示一个空指针异常,而是返回了一个Optional.empty。
2.2:获取Optional的值
Optional获取值的方法为get()方法,但是如果Optional的值为null时,调用get方法则会抛出个NoSuchElementEsception异常。源码为:

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

样例代码如下:

Optional<String> s1 = Optional.ofNullable("测试get方法获取值");
System.out.println(s1.get());
Optional<Object> s2 = Optional.ofNullable(null);
System.out.println(s2.get());

运行结果为:
image
从上面的结果可以看到当Optional的值为null时,调用get方法会抛出一个NoSuchElementException。
从上面get方法的样例可以看出,当Optional的值为null时,直接调用get方法会抛出一个异常,所以这里在调用之前就需要先判断Optional的值是否为null,而判断的则会有两个方法,分别是isPresent()和ifPresent()。源码为:

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

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

样例代码为:

Optional<String> s1 = Optional.ofNullable("测试get方法获取值");
System.out.println(s1.isPresent());
if (s1.isPresent()) {
    System.out.println(s1.get());
} else {
    System.out.println("s1的值为null");
}
s1.ifPresent(u -> System.out.println(u.replace("get", "java")));
Optional<String> s2 = Optional.ofNullable(null);
System.out.println(s2.isPresent());
if (s2.isPresent()) {
    System.out.println(s2.get());
} else {
    System.out.println("s2的值为null");
}
s2.ifPresent(u -> System.out.println(u.replace("get", "java")));

运行结果为:
image
从上面的样例可以看出isPresent()方法是判断该参数值是否为null,不为null就返回true,为null则返回false。而ifPresent()方法则是先看Optional的值是否为null,如果不为null则进行后面括号里的操作,如果为null则不进行处理。
2.3:filter过滤值
Optional的filter()方法是一个过滤方法,其中的参数是Predicate断言型函数式接口。源码为:

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

样例代码为:

Optional<String> s = Optional.ofNullable("10");
System.out.println(s.filter(u -> u.equals("5")));
System.out.println(s.filter(u -> u.equals("10")));

运行结果为:
image
从上面样例的结果可以看出,filter是进行一个过滤函数,当该Optional的值符合过滤条件时,则会返回该Optional,如果不符合时,则会返回Optional.empty。
2.4:map转换值
Optional的map函数可以对已有的Optional的值进行一些转换,当其值不存在时,则会直接返回empty,值存在时才会进行相关的处理。主要的方法有map()方法和flatMap()方法,不过flatMap()方法与map()方法也是有区别的,flatMap()方法的 参数类型需要转化为Optional,而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));
    }
}



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

样例代码为:

Optional<Object> s = Optional.ofNullable("10");
System.out.println(s.get() instanceof Integer);
System.out.println(s.map(u -> Integer.valueOf(u.toString())).get() instanceof Integer);
Optional<Object> s2 = Optional.ofNullable(null);
System.out.println(s2.map(u -> Integer.valueOf(u.toString())));

Optional<Object> s3 = Optional.ofNullable("10");
System.out.println(s3.get() instanceof Integer);
System.out.println(s3.flatMap(u -> Optional.ofNullable(Integer.valueOf(u.toString()))).get() instanceof Integer);
Optional<Object> s4 = Optional.ofNullable(null);
System.out.println(s4.flatMap(u -> Optional.ofNullable(Integer.valueOf(u.toString()))));

运行结果为:
image
从结果可以看出其将值转化为了Integer类型,如果值不存在的话则会返回一个empty。
2.5:默认操作
Optional的默认操作有三个方法,分别是orElse(),orElseGet(),orElseThrow()这三个方法,这三个方法都是当Optional的值为null时会进行一些默认操作,不过这三个方法也是有些区别的,orElse()方法返回的值是直接传入的参数值,orElseGet()方法返回的值则是通过Supplier来获取的,而orElseThrow()方法则是会直接抛出一个异常。他们三个方法的源码如下:

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

样例代码:

Optional<Object> s = Optional.ofNullable("10");
Optional<Object> s1 = Optional.ofNullable(null);

System.out.println(s.orElse("No Value!"));
System.out.println(s1.orElse("No Value!"));
System.out.println(s.orElseGet(() -> new String("No Value")));
System.out.println(s1.orElseGet(() -> new String("No Value")));
System.out.println(s.orElseThrow(() -> new RuntimeException("s参数没有值")));
System.out.println(s1.orElseThrow(() -> new RuntimeException("s1参数没有值")));

运行结果为:
image
从上面的结果可以看出,这几个orElse(),orElseGet(),orElseThrow()方法只是当Optional的值为null时才会进行后面的操作,如果不为null,则还是返回Optional的值