美文网首页Spring-boot
【Spring-boot】Java8 Optional

【Spring-boot】Java8 Optional

作者: 希崽家的小哲 | 来源:发表于2017-09-17 17:02 被阅读472次

    一、背景

    有时候在处理业务逻辑时,需要判断方法返回的值是否为 null 。如,根据用户ID查找用户,Service层代码如下:

    public User findUserById(int id) {
            return userMapper.findUserById(id);
        }
    

    Controller层代码如下:

    User user = userService.findUserById(id);
    if(user==null)
     //throw exception
    else
    //ok
    

    新版本的Java,比如Java 8引入了一个新的Optional类。Optional类的Javadoc描述如下:
    这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

    二、用法

    1. of

    为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

    //调用工厂方法创建Optional实例
    Optional<String> name = Optional.of("Sanaulla");
    //传入参数为null,抛出NullPointerException.
    Optional<String> someNull = Optional.of(null);
    

    2. ofNullable

    为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
    ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况。示例如下:

    //下面创建了一个不包含任何值的Optional实例
    //例如,值为'null'
    Optional empty = Optional.ofNullable(null);
    

    3. isPresent

    如果值存在返回true,否则返回false。

    //isPresent方法用来检查Optional实例中是否包含值
    if (name.isPresent()) {
      //在Optional实例内调用get()返回已存在的值
      System.out.println(name.get());//输出Sanaulla
    }
    

    4. map

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

    //map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
    //为lambda表达式的返回值创建新的Optional实例作为map方法的返回值。
    Optional<String> upperName = name.map((value) -> value.toUpperCase());
    System.out.println(upperName.orElse("No value found"));
    

    完整实例

    public class OptionalDemo {
     
      public static void main(String[] args) {
        //创建Optional实例,也可以通过方法返回值得到。
        Optional<String> name = Optional.of("Sanaulla");
     
        //创建没有值的Optional实例,例如值为'null'
        Optional empty = Optional.ofNullable(null);
     
        //isPresent方法用来检查Optional实例是否有值。
        if (name.isPresent()) {
          //调用get()返回Optional值。
          System.out.println(name.get());
        }
     
        try {
          //在Optional实例上调用get()抛出NoSuchElementException。
          System.out.println(empty.get());
        } catch (NoSuchElementException ex) {
          System.out.println(ex.getMessage());
        }
     
        //ifPresent方法接受lambda表达式参数。
        //如果Optional值不为空,lambda表达式会处理并在其上执行操作。
        name.ifPresent((value) -> {
          System.out.println("The length of the value is: " + value.length());
        });
     
        //如果有值orElse方法会返回Optional实例,否则返回传入的错误信息。
        System.out.println(empty.orElse("There is no value present!"));
        System.out.println(name.orElse("There is some value!"));
     
        //orElseGet与orElse类似,区别在于传入的默认值。
        //orElseGet接受lambda表达式生成默认值。
        System.out.println(empty.orElseGet(() -> "Default Value"));
        System.out.println(name.orElseGet(() -> "Default Value"));
     
        try {
          //orElseThrow与orElse方法类似,区别在于返回值。
          //orElseThrow抛出由传入的lambda表达式/方法生成异常。
          empty.orElseThrow(ValueAbsentException::new);
        } catch (Throwable ex) {
          System.out.println(ex.getMessage());
        }
     
        //map方法通过传入的lambda表达式修改Optonal实例默认值。 
        //lambda表达式返回值会包装为Optional实例。
        Optional<String> upperName = name.map((value) -> value.toUpperCase());
        System.out.println(upperName.orElse("No value found"));
     
        //flatMap与map(Funtion)非常相似,区别在于lambda表达式的返回值。
        //map方法的lambda表达式返回值可以是任何类型,但是返回值会包装成Optional实例。
        //但是flatMap方法的lambda返回值总是Optional类型。
        upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
        System.out.println(upperName.orElse("No value found"));
     
        //filter方法检查Optiona值是否满足给定条件。
        //如果满足返回Optional实例值,否则返回空Optional。
        Optional<String> longName = name.filter((value) -> value.length() > 6);
        System.out.println(longName.orElse("The name is less than 6 characters"));
     
        //另一个示例,Optional值不满足给定条件。
        Optional<String> anotherName = Optional.of("Sana");
        Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
        System.out.println(shortName.orElse("The name is less than 6 characters"));
     
      }
     
    }
    

    输出:

    Sanaulla
    No value present
    The length of the value is: 8
    There is no value present!
    Sanaulla
    Default Value
    Sanaulla
    No value present in the Optional instance
    SANAULLA
    SANAULLA
    Sanaulla
    The name is less than 6 characters

    原文链接: javacodegeeks 翻译: ImportNew.com - 高俊阳译文链接: http://www.importnew.com/6675.html

    三、改进

     public Optional<User> findUserById(int id) {
            return Optional.ofNullable(userMapper.findUserById(id));
        }
    
     public ResponseEntity<?> findUserById( @PathVariable("id") int id){
            log.info("======enter UserController method======");
    
            return userService
                    .findUserById(id)
                    .map(ResponseEntity::ok)
                    .orElseThrow(() -> new ResourceNotFoundException()
                            .setResourceName(ResourceNameConstant.USER)
                            .setId(id));
    
        }
    

    相关文章

      网友评论

        本文标题:【Spring-boot】Java8 Optional

        本文链接:https://www.haomeiwen.com/subject/ujcmsxtx.html