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

Java8 之Optional 的使用

程序员文章站 2024-03-14 17:44:52
...

     作为java8的新特性之一,可选在没有接触之前没有感受到过他的魅力,当真正的去用它才感觉到魅力之所在。可选,JAVA新增的工具类,主要是用来解决我们之前  NullPointException的问题。

    我先贴一段之前的代码,部分截取,真实业务场景中所用到的代码。

if(bidId!= null){
                //根据投标单ID,查询评标人ID --EmpId
                List <SrmBidScore> srmBidScores = srmBidExamMapper.bidScoreByBid(bidId); //查询评分表信息
                if(srmBidScores!= null){
                    for(SrmBidScore srmBidScore:srmBidScores){
                        Long empId = srmBidScore.getEmpId(); //获取评分表中的empId
                        if(empId!= null){
                            employeeList.add(employeeMapper.employeeBy(EMPID)); //根据评分表中的EMPID获取评分人信息
                        }
                    }
                    srmBidGroupListView.setEmployeeList(EmployeeList的); //将获取到的评分人,添加到评分小组信息中
                }
            }

  我们发现,每涉及到一块逻辑判断都要保证前一步所使用的参数值不能是空,否者的话下面的方法就会报NullPointException 的问题。看着是逻辑特别乱,别人在看代码时候,也不便于阅读。

   今天的主角Optional工具类就是教我们如何优雅的来解决这个问题;

一、创建Optional对象

   直接上图,会发现有三个构造方法:ofNullable(T value),of(T value),empty()

   Java8 之Optional 的使用

三者区别:

   of 

 创建一个非空Optional

  ofNullable 

 创建一个可以为空的Optional对象,与of区别就是,可以传入Null参数,如果参数为空,则调empty()方法,有值得话调用 of()方法。可以通过源码解读到。 
/**
     * Returns an {@code Optional} describing the specified value, if non-null,
     * otherwise returns an empty {@code Optional}.
     *
     * @param <T> the class of the value
     * @param value the possibly-null value to describe
     * @return an {@code Optional} with a present value if the specified value
     * is non-null, otherwise an empty {@code Optional}
     */
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }

   empty

  创建一个空的Optional对象。

 所以说我们一般使用的话,就是直接使用ofNullable()来创建Optional对象实例。

二、Optional 方法

  . get 

    获取Option对象中传入的值,如果对象有值返回Optional类型的值,如果传入值为空的话,会抛出 NoSuchElementException 常;

User user = new User();
        user.setName("Tom");
        user.setAge("18");
        Optional<User> OptionalUser = Optional.ofNullable(user);
        System.out.println("-optional-ofNullable:" + OptionalUser.get());//-optional-of:User{name='Tom', age='18'}
Optional<User> OptionalUser = Optional.ofNullable(null);

        System.out.println("-optional-ofNullable:" + OptionalUser.get());//Exception in thread "main" java.util.NoSuchElementException: No value present

源码

 /**
     * If a value is present in this {@code Optional}, returns the value,
     * otherwise throws {@code NoSuchElementException}.
     *
     * @return the non-null value held by this {@code Optional}
     * @throws NoSuchElementException if there is no value present
     *
     * @see Optional#isPresent()
     */
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");//如果传入值为空直接抛出异常
        }
        return value;
    }

.map *

    如果有值,则对其执行调用mapping函数得到返回值。如果传入值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional.

   *map方法会将传入的lambda表达式的参数对原始的Optional值做修改;返回新的Optional实例作为map方法的返回值。

 Optional<String> OptionalString = Optional.ofNullable("abc");
        System.out.println(OptionalString.map((v) -> v.toUpperCase()));//Optional[ABC] 
源码:
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();//如果传入的Optional对象为空,直接返回Optional空对象
        else {
            return Optional.ofNullable(mapper.apply(value));//如果不为空返回mapper函数得到返回值
        }
    }

.flatMap

   如果有值返回mapper函数执行的Optional类型的值,没有值返回空Optional对象;

* flatMap方法与map方法似,区在于mapping函数的返回不同。map方法的mapping函数返回可以是任何T,而flatMap方法的mapping函数必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));
        }
    }

.filter

从字面理解应该是对Optional对象进行过滤;

通过传入lambda表达式件对Optional实例的值进行过滤。对于filter函数我们应该传入实现了Predicate接口的lambda表达式。如果返回同一个Option实例,否则返回空Optional

Optional<String> OptionalString = Optional.ofNullable("abc");
        System.out.println(OptionalString.filter((v)->v.length()>4));//Optional.empty   v的长度小于4,返回空的Optional对象

源码:

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

.ifPresent  

  如果Optional实例有值则为其调用consumer,否不做理; ifpersent方法接受lanbda表达式作为参数

        Optional<User> OptionalUser = Optional.ofNullable(user);
        OptionalUser.ifPresent((value)->{
            System.out.println(value.getName());});//Tom
源码:
public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

.orElse 

如果有值将值返回,没有值返回指定的值,这个好理解一点,只需要关注Optional实例对象是否有值就行。

Optional<String> OptionalString = Optional.ofNullable("abc");
        System.out.println("orElse:"+OptionalString.orElse("def"));//有值得情况返回abc,如果我们构造对象时传入null,则返回def

源码:

public T orElse(T other) {
        return value != null ? value : other;//很清楚
    }

.orElseGet

  orElseGetorElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。

Optional<String> OptionalString = Optional.ofNullable("abc");
        System.out.println("orElseGet:"+ OptionalString.orElseGet(()-> "wasd"));//有值情况和orElse一样返回(abc),没有的话返回lambda表达式返回的‘wasd’

源码:

public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

.orElseThrow

   如果有值则将其返回,否则抛出supplier接口创建的异常;orElseThrow与orElse方法类似,返回默认值不同。

public class orElseThrowException extends Throwable{//异常类定义
    orElseThrowException() {
        super();
    }

    orElseThrowException(String msg) {
        super(msg);
    }

    @Override
    public String getMessage() {
        return "orElseThrowException";
    }

}
Optional<String> OptionalString = Optional.ofNullable(null);//这里我们在其构造对象时传入null
        try{
        OptionalString.orElseThrow(orElseThrowException::new);
        }catch (Throwable e){
            System.out.println("异常捕获");
            System.out.println(e.getMessage());//打印orElseThrowException,自定义的异常
        }
源码:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }