• 为了解决空指针异常

    //Pre-Java 8
    if(str!=null){
        System.out.println(str);
    }
    
    //Java 8
    Optional.ofNullable(str).ifPresent(System.out::println);
    
  • Optional实际上是一个容器,可以保存任意类型的值,或者仅保存null。Optional提供很多有用的方法,这样我们就不用显示进行空指针检测。
  • 它比if语句好在代码可读性更好,而且它提供的是编译时检测,能极大的降低NPF。
  • Optional.of()或者Optional.ofNullable():创建Optional对象,差别在于of不允许参数是null,返回一个包含参数的Optional对象;而ofNullable则无限制,为null则返回一个不包含值的Optional对象(底层是根据参数为null否来选择调用of()/empty()。

    // 参数不能是null
    Optional<Integer> optional1 = Optional.of(1);
    
    // 参数可以是null
    Optional<Integer> optional2 = Optional.ofNullable(null); //返回null
    
    // 参数可以是非null
    Optional<Integer> optional3 = Optional.ofNullable(2);
    
  • Optional.empty():返回一个不包含值的Optional对象:

    Optional<Integer> optional1 = Optional.ofNullable(null);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    System.out.println(optional1 == optional2);// true
    System.out.println(optional1 == Optional.<Integer>empty());// true
    
    Object o1 = Optional.<Integer>empty();
    Object o2 = Optional.<String>empty();
    System.out.println(o1 == o2);// true
    
  • isPresent():判断值是否存在

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    // isPresent判断值是否存在
    System.out.println(optional1.isPresent() == true);
    System.out.println(optional2.isPresent() == false);
    
  • ifPresent(Consumer consumer):如果option对象保存的值不是null,则调用consumer对象,否则不调用(调用指的是重写Consumer接口的方法,重写了什么内容就照着执行)

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    // 如果不是null,调用Consumer
    optional1.ifPresent(new Consumer<Integer>() {
        @Override
        public void accept(Integer t) {
            System.out.println("value is " + t);
        }
    });
    
    // null,不调用Consumer
    optional2.ifPresent(new Consumer<Integer>() {
        @Override
        public void accept(Integer t) {
            System.out.println("value is " + t);
        }
    });
    
  • orElse(value):如果optional对象保存的值不是null,则返回原来的值,否则返回value

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    // orElse
    System.out.println(optional1.orElse(1000) == 1);// true
    System.out.println(optional2.orElse(1000) == 1000);// true
    
  • orElseGet(Supplier supplier):功能与orElse一样,只不过orElseGet参数是一个对象

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    System.out.println(optional1.orElseGet(() -> {
        return 1000;
    }) == 1);//true
    
    System.out.println(optional2.orElseGet(() -> {
        return 1000;
    }) == 1000);//true
    
  • orElseGet(Supplier supplier):功能与orElse区别在于,orElseGet()传入的参数为一个Supplier接口的方法重写,当Optional中有值时,返回值;否则返回从Supplier获得的值。

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    System.out.println(optional1.orElseGet(() -> {
        return 1000;
    }) == 1);//true
    
    System.out.println(optional2.orElseGet(() -> {
        return 1000;
    }) == 1000);//true
    
  • orElseThrow():值不存在则抛出异常,存在则什么不做。好处在于我们可以决定抛出什么样的异常,而不总是NPE。用途举例:查询某个实体时,如果数据库中不存在该记录就可以抛出EntityNotFoundException,处理EntityNotFoundException的方法中我们可以给客户端返回404状态码和异常信息。

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    optional1.orElseThrow(()->{throw new IllegalStateException();});
    
    try
    {
        // 抛出异常
        optional2.orElseThrow(()->{throw new IllegalStateException();});
    }
    catch(IllegalStateException e )
    {
        e.printStackTrace();
    }
    
  • filter(Predicate):判断Optional对象中保存的值是否满足Predicate,是则返回原来的Optional对象,否则返回空的Optional。

    Optional<Integer> optional1 = Optional.ofNullable(1);
    Optional<Integer> optional2 = Optional.ofNullable(null);
    
    Optional<Integer> filter1 = optional1.filter((a) -> a == null);
    Optional<Integer> filter2 = optional1.filter((a) -> a == 1);
    Optional<Integer> filter3 = optional2.filter((a) -> a == null);
    System.out.println(filter1.isPresent());// false
    System.out.println(filter2.isPresent());// true
    System.out.println(filter2.get().intValue() == 1);// true
    System.out.println(filter3.isPresent());// false
    
  • get():从Optional实例中取回实际值对象,实例不存在抛出NPE

    String name="John";
    Optional<String> opt=Optional.ofNullable(name);
    assertEquals("John",opt.get());
    
  • map():返回一个Optional对象,它包含的是函数式接口的返回值,如果返回值为null则这个Optional就是一个空Optional对象

    • 源码

    • 应用

      User user=new User("anna@gmaiil.com","1234");
      String email=Optional.ofNullable(user);
                          .map(u -> u.getEmail())
                          .orElse("default@gmail.com");
      assertEquals(email,user.getEmail());
      
  • flatMap():用法上和map()相同,但参数要求必须是Optional对象

    Optional<String> username=Optional.ofNullable(getUserById())
                                    .flatMap(user -> Optional.of(user.getUsername()))
                                    .flatMap(name -> Optional.of(name.toLowerCase()));
    

    用法

  • 假设有一个Person类,含有Address属性,Address属性包含code字段

    //Person类
    public class Person {
        private Address address;
    
        public Address getAddress() {
            return address;
        }
        public void setAddress(Address address) {
            this.address = address;
        }
    }
    
    //Address类
    public class Address {
        private String code;
    
        public String getCode() {
            return code;
        }
        public void setCode(String code) {
            this.code = code;
        }
    }
    
    //检查这些属性是否是valid的,可以看到,篇幅很长
    private boolean validAddress(Person person){
        if(person!=null){ //第一层判断
            if(person.getAddress()!=null){ //第二层
                String code=person.getAddress().getCode();
                return code!=null; //第三层
            }else{
                return false;
            }
        }else{
            return false;
        }
    }
    
  • 但如果预先就将这些属性设置为Optional(或者在判断时构造为Optional),那么看起来会稍微舒服一点

    //Person类
    public class Person {
        private Optional<Address> address;
    
        public Optional<Address> getAddress() {
            return address;
        }
    
        public void setAddress(Optional<Address> address) {
            this.address = address;
        }
    }     
    
    //Address类
    public class Address {
        private Optional<String> code;
    
        public Optional<String> getCode() {
            return code;
        }
        public void setCode(Optional<String> code) {
            this.code = code;
        }
    }
    
    //判断
    private boolean validAddress2(Person person2){
        Optional<Person> person=Optional.ofNullable(person2);
        return person.flatMap(Person::getAddress)
                     .flatMap(Address::getCode)
                     .filter(x -> x.length()>6)
                     .isPresent();
    }
    
  • 代码实例:SpringMvc02/Test1、Person、Address