本文共 4723 字,大约阅读时间需要 15 分钟。
optional<T>
对象是一种包装器对象,要么包装了类型T对象,要么没有包装任何对象。对于第一种情况,称这种值为存在的。Optional<T>类型被当做一种更安全的方式,用来替代类型T的引用,这种引用要么引用某个对象,要么为null。但是,它只有在正确使用的情况下才会更安全。
有效地使用Optional的关键是要使用这样的方法:它在值不存在的情况下会产生一个可替代物品,而只有在值存在的情况下才会使用这个值。
通常,在没有任何匹配时,我们会希望使用某种默认值,可能是空字符串:
String result = optionalString.orElse("");//The wrapped string, or "" if none
你还可以调用代码来计算默认值:
String result = optionlString.orElseGet(() -> Locale.getDefault().getDisplayName());//The function is only called when needed
或者可以在没有任何值时抛出异常:
String result = optionalString.orElseThrow(IllegalAccessException::new);
另一种使用可选值的策略是只有在其存在的情况下才消费该值。
ifPresent方法会接受一个函数。如果该可选值存在,那么它会被传递给该函数。否则,不会发生任何事情:
optionalString.ifPresent(v -> Process v);
如果在该值存在的情况下想要将其添加到某个集中,那么就可以调用:
optionalString.ifPresent(v -> results.add(v));
或者直接调用:
optionalString.ifPresent(results::add);
当调用ifPresent时,从该函数不会返回任何值。如果想要处理函数的结果,应该使用map:
Optionaladded = optionalString.map(results::add);
方法 | 说明 |
---|---|
T orElse(T other) | 产生这个Optional的值,或者在该Optional为空时,产生other |
T orElseGet(Supplier<? extends T> other) | 产生这个Optional的值,或者在该Optional为空时,调用other的结果 |
<X extends Throwabled> T orElseThrow(Supplier<? extends X> exceptionSupplier) | 产生这个Optional的值,或者在该Optional为空时,抛出调用exceptionSupplier的结果 |
void ifPresent(Consumer<? super T> consumer) | 如果该Optional不为空,那么就将它的值传递给consumer |
<U> Optional<U> map(Function<? super T, ? extends U> mapper) | 产生将该Optional的值传递给mapper后的结果,只要这个Optional不为空且结果不为null,否则产生一个空Optional。 |
get方法会在Optional值存在的情况下获得其中包装的元素,或者在不存在的情况下抛出一个NoSuchElementException对象。因此:
OptionaloptionalValue = ...;optionalValue.get().someMethod();//并不比下面的方式更安全T value = ...;value.someMethod();
ifPresent方法会报告某个Optional<T>对象是否具有一个值,但是
if(optionalValue.isPresent()) optionalValue.get().someMethod();//并不比下面的方法更容易处理if(value != null) value.someMethod();
方法 | 说明 |
---|---|
T get() | 产生这个Optional的值,或者在该Optional为空时,抛出一个NoSuchElementException |
boolean isPresent() | 如果该Optional不为空,则返回true |
Optional.of(result) 和 Optional.empty()
public static Optionalinverse(Double x) { return x == 0 ? Optional.empty() : Optional.of(1 / x); }
ofNullable方法被用啦作为可能出现的null值和可选值之间的桥梁:
Optional.ofNullable(obj)会在obj不为null的情况下返回Optional.of(obj),否则会返回Optional.empty()。
方法 | 说明 |
---|---|
static <T> Optional<T> of(T value) static <T> Optional<T> ofNullable(T value) | 产生一个具有给定值的Optional。如果value为null,那么第一个方法抛出一个具有给定值的NullPointerExcepion对象,而第二个方法会产生一个空optional。 |
static <T> Optional<T> empty() | 产生一个空Optional。 |
假如有一个可以产生Optional对象的方法f、并且目标类型T具有一个可以产生Optional对象的方法g。如果他们都是普通的方法,那么你可以通过调用s.f().g()来将他们组合起来。但是这种组合没法工作,因为s.f()的类型为Optional<T>,而不是T。因此,需要调用:
Optional result = s.f().flatMap(T::G);
如果s.f()的值存在,那么g就可以应用到它上面。否则,就会返回一个空Optional。
很明显,如果有更多的可以产生Optional值的方法或Lambda表达式,那么就可以重复此过程。你可以直接将flatMap的调用链接起来,从而构建由这些步骤构成的管道,只有所有步骤都成功时,该管段才会成功。
package pers.zhang;import java.util.*;/** * @Author: acton_zhang * @Date: 2020/3/25 11:49 上午 * @Version 1.0 */public class OptionalTest { public static void main(String[] args) { String[] strs = { "one", "two", "three", "four", "five"}; ListwordList = Arrays.asList(strs); Optional o = wordList.stream().filter(s -> s.contains("o")).findFirst(); System.out.println(o.orElse("No word contains o")); Optional optionalString = Optional.empty(); String result = optionalString.orElse("N/A"); System.out.println("result:" + result); result = optionalString.orElseGet(() -> Locale.getDefault().getDisplayName()); System.out.println("result:" + result); try { result = optionalString.orElseThrow(IllegalAccessException::new); System.out.println("result:" + result); } catch (IllegalAccessException e) { e.printStackTrace(); } optionalString = wordList.stream().filter(s -> s.contains("e")).findFirst(); optionalString.ifPresent(s -> System.out.println(s + "contains e")); Set results = new HashSet<>(); optionalString.ifPresent(results::add); Optional added = optionalString.map(results::add); System.out.println(added); System.out.println(inverse(4.0).flatMap(OptionalTest::squareRoot)); System.out.println(inverse(-1.0).flatMap(OptionalTest::squareRoot)); System.out.println(inverse(0.0).flatMap(OptionalTest::squareRoot)); Optional result2 = Optional.of(-4.0) .flatMap(OptionalTest::inverse) .flatMap(OptionalTest::squareRoot); System.out.println(result2); } public static Optional inverse(Double x) { return x == 0 ? Optional.empty() : Optional.of(1 / x); } public static Optional squareRoot(Double x) { return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x)); }}
转载地址:http://fvpqb.baihongyu.com/