错误用法:
1、先使用isPresent来判断是否有值,然后使用get()方法取出元素。
Optional<String> optional = Optional.empty(); if (optional.isPresent()) { String str = optional.get(); } public boolean isPresent() { return value != null; }说明:我直接用!Objects.isNull()判断下,再处理它不香吗?为什么还要用这个Optional呢?
2、使用Optional作为方法参数来使用
void badMethod(Optional<String> optional) { ...; }说明:每个方法都应该对参数进行合法性校验的,除非是内部使用的private方法,我们确定参数的取值情况时可以不进行校验。这个方法的参数意思就是说:我会判断是否为空的(用的错误方法1),你们放心传给我参数就好了。这不是废话?
3、使用Optional来作为类的成员属性
public class BadClass { private Optional<String> optional; ... }说明: 类的成员属性,对象类型的默认值本来就是null的,你搞一个Optional来当成员属性是几个意思??难道是:“大家好!我这个类的属性是可能为null的,我考虑很周到的,我代码逼格很高的”。我表示很无语,因为真的有“前辈”这么用的!
正确用法:
定义方法的返回值的类型为Optional,因为方法的返回值可能为空,也可能有值的。根据返回值的情况,有选择性的处理相应的逻辑。这里我把“有选择性的”标记了,因为这个就是Optional的中文意思,也是它的用法所代表的意思。
两个成员属性:封装的值、空Optional对象
/*空Optional对象*/ private static final Optional<?> EMPTY = new Optional<>(); /*封装的值*/ private final T value;empty方法的使用:返回的就是静态的成员属性EMPTY
public static<T> Optional<T> empty() { Optional<T> t = (Optional<T>) EMPTY; return t; }先看下创建Optional对象的两个方式:(这个不是重点)
1、Optional.of():
public static <T> Optional<T> of(T value) { return new Optional<>(value); } private Optional(T value) { this.value = Objects.requireNonNull(value); } public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; }说明:可以看到如果传一个null给of方法的话,会直接抛一个空指针异常,还有一个是optional.get()方法,如果value为空的话,也是直接抛异常的。说明人家作者根本不是说要用Optional来防止NullPointerException异常的发生的,而是用一种有选择性的简洁的方式去处理一个可能为空的对象,不知道怎么就被误认为了用Optional就没有空指针异常的问题了。
2、Optional.ofNullable():
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }这个方法是可以传入null值的,不会抛出空指针异常。
下面围绕这个“有选择性的”展开介绍:
1、针对一个可能为空的对象,如果有值的话就选择处理这个值,使用ifPresent(Consumer)
public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); }说明:如果value值不为空的话,消费这个值(也就是处理这个值)
用法:
Optional<String> optional = Optional.of("river66"); optional.ifPresent(System.out::println);关于Consumer的使用,可以参考下:https://blog.csdn.net/river66/article/details/108178965
2、针对一个可能为空的对象,如果不符合给定的条件,则作为空处理,使用filter(Predicate)
public Optional<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty(); }关于Predicate的用法,可以参考下:https://blog.csdn.net/river66/article/details/107028467
用法:
Optional<String> optional = Optional.of(""); optional = optional.filter(""::equals);3、针对一个可能为空的对象,只要不是null值,就转化为另一个值,使用map(Function)
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)); } }用法:
Optional<String> optional = Optional.of("123"); Optional<Integer> op = optional.filter((a)->{ boolean b; try { Integer.parseInt(a); b = true; } catch (NumberFormatException e) { b = false; } return b; }).map(Integer::parseInt);说明:如果filter中返回的是false,则意味着value将为null,但是map中调用的是ofNullable,所以map是可以跟在filter后使用的。而flatMap这个方式是不可以跟在filter后面的,因为会抛出NullPointerException。
关于Function的用法,可以参考下:https://blog.csdn.net/river66/article/details/108545027
4、针对一个可能为空的对象,不为空则返回value,为空则返回给定的默认值,使用T orElse(T other)
public T orElse(T other) { return value != null ? value : other; }用法:
Optional<String> optional = Optional.empty(); String notNull = optional.orElse("");5、针对一个可能为空的对象,不为空则返回value,为空则返回给定的默认值(Lambda表达式返回的值,即Supplier),使用orElseGet(Supplier)。
public T orElseGet(Supplier<? extends T> other) { return value != null ? value : other.get(); }用法:
Optional<String> optional = Optional.empty(); String notNull = optional.orElseGet(()->{return "";});6、针对一个可能为空的对象,不为空则返回value,为空就抛异常,使用orElseThrow(Supplier) throws X
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); } }用法:
Optional<String> optional = Optional.empty(); String a = optional.orElseThrow(() -> new NoSuchElementException(""));