Java 8 Optional正确使用姿势

在Java程序中,空指针异常(NullPointerException)可以说是最常见的的了,所以我们在打代码的时候会到处使用if(null == A){ ...... }这类操作。Java 8提供了Optional类型来一定程度上缓解NPE问题,这里主要因为自己在使用Optional类型时候踩到一些坑,故作此总结加深印象。

Optional是什么

Optional是什么?有什么作用?什么时候该用?什么时候最好不用?这里我也不去网上搜索搬定义了,直接读源码类上的注释说明就可以明白了

package java.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**    ----Optional是什么----
 * A container object which may or may not contain a non-{@code null} value.
 * If a value is present, {@code isPresent()} returns {@code true}. If no
 * value is present, the object is considered <i>empty</i> and
 * {@code isPresent()} returns {@code false}.
 *    ----Optional的附加方法说明----
 * <p>Additional methods that depend on the presence or absence of a contained
 * value are provided, such as {@link #orElse(Object) orElse()}
 * (returns a default value if no value is present) and
 * {@link #ifPresent(Consumer) ifPresent()} (performs an
 * action if a value is present).
 *    ----什么时候不该用Optional----
 * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
 * class; use of identity-sensitive operations (including reference equality
 * ({@code ==}), identity hash code, or synchronization) on instances of
 * {@code Optional} may have unpredictable results and should be avoided.
 *    ----什么时候用Optional----
 * @apiNote
 * {@code Optional} is primarily intended for use as a method return type where
 * there is a clear need to represent "no result," and where using {@code null}
 * is likely to cause errors. A variable whose type is {@code Optional} should
 * never itself be {@code null}; it should always point to an {@code Optional}
 * instance.
 *
 * @param <T> the type of value
 * @since 1.8
 */

正确使用姿势

1 使用Optional 的目的主要是为了清晰地表达返回值中没有结果的可能性

所以一般只用来作为方法的返回值类型,例如:

Optional 是不可变类型,是加了final修饰的类,并且,它是没用共有构造器的,所以我们没办法new出一个Optional 来,我们只能使用它所提供的三个方法来得到Optional 对象:

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

// 2 
public static <T> Optional<T> of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
    }
// 3 
public static <T> Optional<T> ofNullable(T value) {
        return value == null ? (Optional<T>) EMPTY
                             : new Optional<>(value);
    }

下面是个人对Optional 使用的一些总结:

2 不要直接给Optional 赋null值

3 如果不能保证对象一定不为null,那就用Optional .ofNullable(),因为Optional .of()会抛NPE

    /**
     * Returns an {@code Optional} describing the given non-{@code null}
     * value.
     *
     * @param value the value to describe, which must be non-{@code null}
     * @param <T> the type of the value
     * @return an {@code Optional} with the value present
     * @throws NullPointerException if value is {@code null} //这里明确了value为空会NPE!!!
     */
    public static <T> Optional<T> of(T value) {
        return new Optional<>(Objects.requireNonNull(value));
    }

    /**
     * Returns an {@code Optional} describing the given value, if
     * non-{@code null}, otherwise returns an empty {@code Optional}.
     *
     * @param value the possibly-{@code null} value to describe
     * @param <T> the type of the value
     * @return an {@code Optional} with a present value if the specified value
     *         is non-{@code null}, otherwise an empty {@code Optional}
     */
    @SuppressWarnings("unchecked")
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? (Optional<T>) EMPTY
                             : new Optional<>(value);
    }

4 使用isEmpty()或isPresent()来作为判断value是否为空,而不是if(optional1 == null) {...}

5 使用orElse, orElseGet, orElseThrow这几个API来避免自己写if else语句

6 使用equals方法判断Optional对象是否相等,而不是使用“==”

因为Optional类已经覆盖了equals方法,所以想必你已经能猜到上面的输出结果了吧

7 使用filter对value对象做业务逻辑判断

首先我们在Shop类中加个如下简单的业务逻辑判断方法,然后再进行测试看看结果:

    //在Shop类中加个简单的业务逻辑判断方法
    public Boolean isRecommanded(){
        if (Objects.equals(this.shopId,1L)){
            return true;
        }
        return false;
    }

如果提供给filter中的返回false,那么就会得到一个空的Optional,而这时再调用get方法就会报如上错误,所以在使用Optional的get方法前一定要使用isPresent()方法先判断!

以上就是个人对Optional学习和使用的一些总结,以此文记录一番

原文地址:https://www.cnblogs.com/kuangdw/p/15023307.html