• Java Optional类


    一、背景

    1. Optional类主要解决空指针异常的问题,避免显式判断空指针,减少null的防御性检查

    2. 借鉴了google guava的Optional类

    3. Optinal类里有一个字段value,主要就是对value是否为Null的判断和操作

    4. Optional对象可以看做是一种容器对象

    二、创建Optional类的实例,1个构造方法,3个静态方法

    1. 构造方法 private Optional(T value),因为是私有的,不能被外部访问,也就不能调用构造方法创建对象,会报空指针异常

        private Optional(T value) {
            this.value = Objects.requireNonNull(value);
        }

    2. of()静态方法,底层调用私有构造方法,依然会报空指针异常

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

    Optional<String> optStr1 = Optional.of("optional");

    3. empty()静态方法,不报空指针,返回一个值为null的Optional对象

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

    Optional<String> optStr = Optional.empty();

    4. ofNullable()静态方法,底层调用empty()和of()方法,如果传入的值为null,就返回值为null的Optional对象,否则返回值不为null的Optional对象,建议使用

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

    Optional<String> optStr2 = Optional.ofNullable(null);

    三、Optional的使用

    1. get()方法,谨慎使用,返回包装对象的实际值,null会抛NoSuchElementException异常

    2.isPresent() vs ifPresent()

    isPresent()方法,谨慎使用,判断包装对象的实际值是否非空

    ifPresent()方法,接收一个Consumer对象,如果值不为空,执行Consumer对象的accept()方法(有一个参数无返回值)

    注意:千万不要这样写,因为仍然要判断null,跟不使用Optional没区别

    User user = Optional.ofNullable(user);
    if (Optional.isPresent()){
       // TODO: do something
    }

    3. filter()方法,接收一个Predicate对象,即一个判断条件,用于对Optional对象进行过滤

    Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

    4. map() vs flatMap() 用于值转换

    map()方法,接收一个Function<? super T, ? extends U>对象,用Function函数进行计算

    flatMap()方法,接收一个Function<? super T, Optional<U>>对象,用Function函数进行计算

    5. orElse() vs orElseGet() vs orElseThrow()

    orElse()方法,值为null,则返回默认值;即使值不为null,仍然会执行orElse(),不建议使用

    orElseGet()方法,接收一个Supplier对象,用Supplier对象的get()方法作为默认值,当值不为null时,不会执行orElseGet(),建议使用

    orElseThrow()方法,接收一个Supplier对象,Supplier对象必须返回一个异常

    四、实际场景

    1. 

    public String getCity(User user)  throws Exception{
            if(user!=null){
                if(user.getAddress()!=null){
                    Address address = user.getAddress();
                    if(address.getCity()!=null){
                        return address.getCity();
                    }
                }
            }
            throw new Excpetion("取值错误"); 
    }
    
    public String getCity(User user) throws Exception{
        return Optional.ofNullable(user)
                       .map(u-> u.getAddress())
                       .map(a->a.getCity())
                       .orElseThrow(()->new Exception("取指错误"));
    }

    2. 

    if(user!=null){
        dosomething(user);
    }
    
    Optional.ofNullable(user)
             .ifPresent(u->{
                dosomething(u);
    });

    3. 

    public User getUser(User user) throws Exception{
        if(user!=null){
            String name = user.getName();
            if("zhangsan".equals(name)){
                return user;
            }
        }else{
            user = new User();
            user.setName("zhangsan");
            return user;
        }
    }
    
    public User getUser(User user) {
        return Optional.ofNullable(user)
                       .filter(u->"zhangsan".equals(u.getName()))
                       .orElseGet(()-> {
                            User user1 = new User();
                            user1.setName("zhangsan");
                            return user1;
                       });
    }

    4. Optional作为返回值

    参考: 

    https://www.jianshu.com/p/d81a5f7c9c4e

    https://www.cnblogs.com/rjzheng/p/9163246.html

  • 相关阅读:
    实战篇之实现 OutLook 中以 EDM 形式发送通知邮件
    ASP.NET MVC5 之路由器
    ASP.NET MVC5 之数据迁移
    说不出的烦
    ASP.NET MVC5 之 Log4Net 的学习和使用
    读取配置文件参数和文件路径
    序列化和反序列化示例
    面向对象之封装
    面向对象4之常用的乱七八糟
    面向对象三之继承和派生
  • 原文地址:https://www.cnblogs.com/june0816/p/11442923.html
Copyright © 2020-2023  润新知