JAVA之工具类Optional

本文参考自: 原文地址

JAVA之工具类Optional

一.    概述

        Optional类并不像之前介绍的工具都是借口,他是一个被final修饰的具体的类,我们一般拿它做一些对空(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> {
    
    private static final Optional<?> EMPTY = new Optional<>();

    private final T value;
    
    private Optional() {
        this.value = null;
    }
    
    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);
    }

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

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

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

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

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

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

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

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

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

    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }

    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}
        这么多方法是不是惊呆了.首先先从 构造方法讲起.

      1.    empty方法(私有)

        没有入参,直接new出一个Optional实例返回.

      2.    of方法

        接受一个传入类型构造一个包含传入值的Optional实例返回,该方法并没有对入参做非空判定,如果传入的参数是null的话,直接就会抛出异常,可用来阻挡null值的传入.

      3.    ofNullable方法

        看名字就知道,在传入参数的时候,对入参做了非空判定,如果传入的参数是null的话,就会new出来一个新的Optional实例.如果不是null,则构造一个包含传入值的Optional实例返回.
        下面讲解其他方法.

      4.    isPresent方法

        没有入参,返回一个布尔值(boolean).判断调用方法的对象是否为空,为空则返回false,非空则返回true.如同object != null的返回结果.

      5.    get方法

        如果Optional中有值,则返回该值,如果没有,则抛出NoSuchElementException的异常.

      6.    ifPresent方法

        如果Optional中有值,则进行下面的操作,如果为空,则什么也不做.

      7.    orElse方法

        接受一个传入类型,如果Optional中有值,则返回该值,如果为空,则返回默认值

      8.    orElseGet方法

        接受一个Supplier类型的数据,如果Optional中有值,则返回该值,如果为空,则返回一个Supllier生成的一个数据.

      9.    orElseThrow方法

        同第8个方法,只是在为空的时候,抛出一个由Supplier生成的指定异常.

      10.    filter方法

        顾名思义,这是一个过滤方法.传入一个Predicate类型的参数,如果满足Predicate条件,则返回该Optional的值,反之则返回一个空的Optional对象.

      11.    map方法

        如果Optional的值存在,则进行传入的Function接口的方法,并返回其方法结束后的值,并封装成一个Optional的对象,否则返回一个空的Optional对象.

      12.    flatMap方法

        如同第11方法,但是其返回值必须是一个Optianal类型的对象.

二.    示例

        方法较多,我们写几个常用示例,先创建一个用户实体类,有姓名和年龄参数,getter,setter方法,并重写了toString方法方便打印结果:
package com.yczuoxin.demo.optional;

public class User {
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

        1.    传入一个对象,如果是空我们不做任何操作,如果不是空,就讲对象打印出来.

package com.yczuoxin.demo.optional;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        Optional<User> user = Optional.ofNullable(new User("张三",18));
        Optional<User> empty = Optional.ofNullable(null);

        user.ifPresent(existUser -> System.out.println(existUser));
    }
}

测试成功,只打印出了非空的结果.注意,此处如果用of代替ofNullable的话会直接抛出异常.

        2.    传入一个字符串,如果是空,则返回empty string, 如果不是空则返回其值.

package com.yczuoxin.demo.optional;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        Optional<String> str = Optional.ofNullable("string");
        Optional<String> empty = Optional.ofNullable(null);

        System.out.println(str.orElse("new string"));
        System.out.println(empty.orElse("empty string"));
    }
}

也可以使用另一个方法

package com.yczuoxin.demo.optional;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        Optional<String> str = Optional.ofNullable("string");
        Optional<String> empty = Optional.ofNullable(null);

        System.out.println(str.orElseGet(() -> new String("is empty")));
        System.out.println(empty.orElseGet(() -> new String("is empty")));
    }
}

测试成功.

        3.    传入一个用户,如果用户存在,则获取用户的用户名,并将其用户名的字母全部大写输出.

package com.yczuoxin.demo.optional;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        User user = new User("zhangsan",18);
        User empty = null;
        System.out.println(Optional.ofNullable(user).map(user1 -> user1.getName()).map(name -> name.toUpperCase()));
        System.out.println(Optional.ofNullable(empty).map(user1 -> user1.getName()).map(name -> name.toUpperCase()));
    }
}

测试成功.可以看见,如果使用of方法,会报出空指针异常.

        4.    年龄大于20的用户则输出其用户名.

package com.yczuoxin.demo.optional;

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        User zhangsan = new User("zhangsan",18);
        User lisi = new User("lisi",21);
        Optional<String> zhangsanName = Optional.ofNullable(zhangsan).filter(user -> user.getAge() > 20)
                .map(user -> user.getName());
        System.out.println(zhangsanName);
        Optional<String> lisiName = Optional.ofNullable(lisi).filter(user -> user.getAge() > 20)
                .map(user -> user.getName());
        System.out.println(lisiName);
    }
}

测试成功.输出了年龄大于20的用户的姓名.

三.    总结

这个工具类被用作对空的判定.该工具类有几个使用限制:
       1.    单纯使用isPresent方法和get方法跟我们之前的写法并没有什么减少代码书写的工作量,反而还增加了对Optional的封装.
        2.    Optional类没有实现Serializable的接口,所以不能被序列化,即不能作为类的属性或者方法入参.

猜你喜欢

转载自blog.csdn.net/u014333268/article/details/81583862