欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDK8新特性之Optional操作

程序员文章站 2022-01-05 10:51:07
...

1 Optional 类简介

  JDK8 中引入的 Optional 类可以解决空指针异常, 让我们省略繁琐 的非空判断. Optional 类就是一个可以为 null 容器, 或者保存指定类型的数据, 或者为 null.

package java.util;

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

public final class Optional<T> {
    /**
     * Common instance for {@code empty()}.
     */
    private static final Optional<?> EMPTY = new Optional<>();

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;

    /**
     * value为空的Optional类型对象
     */
    private Optional() {
        this.value = null;
    }

    /**
     * 返回一个空的Optional对象
     */
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }

    /**
     * 如果为空,抛出一个空指针异常
     */
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

    /**
     * 封装为一个Optional 类型的对象
     */
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }

    /**
     * 把指定的 value 值封装为 Optional 对象,如果 
     * value 为 null 返回一个空的 Optional 对象
     */
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

    /**
     * 如果值存在返回, 如果不存在抛出异常 NoSuchElementException
     */
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

    /**
     * 判断值是否存在
     */
    public boolean isPresent() {
        return value != null;
    }

    /**
     * 如果值存在就执 行 consumer 函数,否则什么也不做
     */
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    /**
     * 如果有值,返回符合 predicate 条件的 Optional 对象, 否则返回空的 Optional 对象
     */
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    /**
     * 如果值存在 就执行 mapper 映射函数,
     */
    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));
        }
    }

    /**
     * 如果 有值,执行 mapper 映射函数,返回 Optional 对象, 如果没有值返 回空的 Optional 对象
     */
    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));
        }
    }

    /**
     * 如果值存在就返回,如果不存在返回 other
     */
    public T orElse(T other) {
        return value != null ? value : other;
    }

    /**
     * 如果存在就返回值, 如果不存在,执行 Supplier 返回另外一个值
     */
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    /**
     * 如果存在就返回该值,如果不存在抛出由 exceptionSupplier 生成的异常
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 重写equals方法
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Optional)) {
            return false;
        }

        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }

    /**
     * Objects类的hashcode方法
     */
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    /**
     * 重写toString 方法
     */
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

2 Optional 的基本操作

public class Test01 {
    public static void main(String[] args) {

        //1 把一个字符串封装为Optional对象
        //参数不能为null,否则抛出NullPointException
        Optional<String> ofString = Optional.of("hello");

        //Optional<String> ofString1 = Optional.of(null);

        //2 为指定的值创建Optional对象(可以为空)
        Optional<String> ofString2 = Optional.ofNullable(null);
        System.out.println(ofString2);//Optional.empty

        //3 直接创建一个空的Optional对象
        Optional<Object> empty = Optional.empty();
        System.out.println(empty);//Optional.empty

        //4 获得 Optional 对象中的值,如果值不存在会产生异常
        String text = ofString.get();
        System.out.println(text);
        String text2 = ofString2.get(); //java.util.NoSuchElementException

        //5 如果 Optional 对象中有值就返回,没有则返回指定的其他值
        text = ofString.orElse("another");

        //6 如果有值就返回,如果 Optional 对象中没值则创建一个新的
        text = ofString2.orElseGet(() -> "newString");
        System.out.println( text ); //newString

        //7 orElseThrow(),如果值存在就返回,否则抛出异常 /
        text = ofString2.orElseThrow(NullPointerException::new);
        text = ofString.orElseThrow(NullPointerException::new);
        System.out.println( text );


        //8 filter(),如果 Optional 对象有值返回满足指定条件的 Optional 对象
        // , 否则返回空 的 Optional 对象
        text = ofString.filter(s -> s.length() > 10).orElse("lenth is letter than 10");
        System.out.println( text );
        text = ofString.filter(s -> s.length() > 3).orElse("lenth is letter than 3");
        System.out.println( text );


        //9 如果 Optional 对象的值存在,执行 mapper 映射函数
        text = ofString.map(x -> x.toUpperCase()).orElse("Failure");
        System.out.println( text );
        text = ofString2.map(x -> x.toUpperCase()).orElse("Failure");
        System.out.println( text ); //Failure
        
        //10 ifPresent() 如果 Optional 对象有值就执行 Consumer 函数 
        ofString.ifPresent(s -> System.out.println("处理数据" + s)); 
        ofString2.ifPresent(s -> System.out.println("处理数据" + s)); //没有值什么也 不做 System.out.println("optional");


    }
}

3 map() 和filtMap()

4 Optional 使代码更简洁

public class Test02 {
    public static void main(String[] args) {
        Address address = new Address("Beijing", "*");
        User user = new User("zhangsan", address);
        User user1 = new User();
        User user2 = null;
        System.out.println(getName1(user));
        System.out.println(getName2(user1));
        System.out.println(getCity1(user2));
        System.out.println(getCity2(user));
    }

    /**传统写法**/
    //定义方法返回指定用户的用户名 ,如果用户名不存在返回unknown
    public static String getName1(User user) {
        if (user == null) { //判断参数接收的 User 对象是否为 null
            return "unknown";
        }
        return user.name;
    }

    //Optional 可以解决空指针问题
    public static String getName2(User user) {
        return Optional.ofNullable(user)     //把参数接收的 user 对象包装为 Optional 对象
                .map(u -> u.name)            //映射,只需要用户名
                .orElse("unknown");    //存在就返回,不存在返回 unknown
    }

    /**传统写法**/
    //定义方法返回指定用户的城市
    public static String getCity1(User user) {
        if (user != null) {
            if (user.address != null) {
                return user.address.city;
            }
        }
        return "unkown";
    }

    //使用 Optional 返回用户的城市
    public static String getCity2(User user) {
        return Optional.ofNullable(user)    //把参数对象包装为 Optional 对象
                .map(u -> u.address)        //映射用户的地址
                .map(addr -> addr.city)     //映射地址的城市
                .orElse("Unkown");    //有就返回,没有返回 Unknown
    }
}

//定义用户类
class User {
    String name;
    Address address;

    public User(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public User() {
    }
}

class Address {
    String city;
    String house;

    public Address(String city, String house) {
        this.city = city;
        this.house = house;
    }
}

5 Optional 在实际开发中的应用