zoukankan      html  css  js  c++  java
  • Java8的新特性--Optional

    Optional

    一、Optional类是什么?

    Optional 类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在用Optional可以更好的表达这个概念。并且可以避免空指针。

    二、Optional类常用的方法

    1. 创建Optional实例

    这个类型的对象可能包含值,也可能为空。

    1.1 Optional.of(T)

    创建一个Optional实例

        @Test
        public void test01(){
            ////创建一个带泛型的Optional容器类
            Optional<Employee> employee = Optional.of(new Employee());
            System.out.println(employee.get());
    
            //会报空指针异常
            Optional<Employee> employee1 = Optional.of(null);
            System.out.println(employee1.get());
    
        }
    }
    

    这里我们需要注意,Optional.of(null),of方法传null时,会报NullPointException.

    1.2 Optional.empty()

    创建一个空的Optional实例

        @Test
        public void test02(){
            //构建了一个空的Optional实例,里面没有任何东西
            Optional<Employee> employee = Optional.empty();
            System.out.println(employee.get());//输出 java.util.NoSuchElementException: No value present
        }
    

    1.3. Optional.ofNullable(T t)

    Optional类中的of()方法不允许包装null,但是ofNullable()方法可以,传递到该方法中的若为null,则构建一个空的Optional实例

        @Test
        public void test03(){
            //不会报空指针异常
            //Optional类中的of()方法不允许包装null,但是ofNullable()方法可以,传递到该方法中的若为null,则构建一个空的Optional实例
            Optional<Employee> employee2 = Optional.ofNullable(null);
            if(employee2.isPresent()){
                System.out.println(employee2.get());
            }else{
                System.out.println("------------");
            }
        }
    

    我们来看一下ofNullable源码

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

    即如果传进来的是null则直接调用了empty(),不为null时才调用of(value)。

    1.4. 小结

    这个类型的对象可能包含值,也可能为空。我们可以使用Optional.empty()方法创建一个空的Optional,也可以使用of() 和 ofNullable() 方法创建包含值的 Optional。这俩方法的不同之处在于如果把null值作为参数传递进去,of()方法会抛出NullPointerException。所以,我们应该在对象不为 null的时候使用 of(),对象即可能是 null 也可能是非null,使用 ofNullable() 方法。

    2.访问Optional对象的值

    2.1 get()获取值

        @Test
        public void test01(){
            ////创建一个带泛型的Optional容器类
            Optional<Employee> employee = Optional.of(new Employee());
            //获取值
            System.out.println(employee.get());
        }
    

    从 Optional 实例中取回实际值对象的方法之一是使用 get() 方法。不过,这个方法会在值为null的时候抛出异常,为了避免我们要先验证是否有值。

    2.2 isPresent()验证是否有值

        @Test
        public void test03(){
            //不会报空指针异常
            //Optional类中的of()方法不允许包装null,但是ofNullable()方法可以,传递到该方法中的若为null,则构建一个空的Optional实例
            Optional<Employee> employee2 = Optional.ofNullable(null);
            //判断是否存在
            if(employee2.isPresent()){//存在
                System.out.println(employee2.get());
            }else{//不存在
                System.out.println("------------");
            }
        }
    

    2.3 ifPresent()

    检查是否有值的时候还可以用ifPresent(),该方法除了执行检查,还可以接受一个Consumer(消费者)参数,如果对象不是空的,就执行传入的Lambda表达式。

        @Test
        public void test04(){
            Optional<Employee> employee2 = Optional.ofNullable(new Employee());
            //如果对象不是空的,就执行传入的Lambda表达式。
            employee2.ifPresent(e -> System.out.println(e.getAge()));
        }
    

    3. 返回默认值

    Optional类提供API用以返回对象值,或者在对象为空的时候返回默认值。

    3.1 orElse(T t)

    如果调用对象包含有值,那么返回该值,否则返回orElse()方法中的对象。

        @Test
        public void test05(){
            Optional<Employee> op = Optional.ofNullable(new Employee());
            Employee em = op.orElse(new Employee("默认姓名", 20, 1000));
            System.out.println(em);//打印Employee{name='null', age=0, salary=0.0}
    
            Optional<Employee> op1 = Optional.ofNullable(null);
            Employee em1 = op1.orElse(new Employee("默认姓名", 20, 1000));
            System.out.println(em1);//打印Employee{name='默认姓名', age=20, salary=1000.0}
        }
    

    3.2 orElseGet(Supplier s)

        @Test
        public void test06(){
            Optional<Employee> op = Optional.ofNullable(new Employee());
            Employee em = op.orElseGet(() -> new Employee("默认姓名", 20, 1000));
            System.out.println(em);//打印Employee{name='null', age=0, salary=0.0}
    
            Optional<Employee> op1 = Optional.ofNullable(null);
            Employee em1 = op1.orElseGet(() -> new Employee("默认姓名", 20, 1000));
            System.out.println(em1);//打印Employee{name='默认姓名', age=20, salary=1000.0}
        }
    

    3.3 orElse(T t)和orElseGet(Supplier s)的不同

    先来看看传入对象都为null时

    
        public Employee createNewEmployee(){
            System.out.println("==========创建一个新对象====");
            return new Employee("默认姓名1", 20, 1000);
        }
        
        @Test
        public void test07(){
    
            //传入对象都为null时
            Employee e = null;
            Optional<Employee> op = Optional.ofNullable(e);
            System.out.println("-----orElse----");
            Employee em = op.orElse(createNewEmployee());
            System.out.println("-----orElseGet----");
            Employee em1 = op.orElseGet(() -> createNewEmployee());
        }
    

    运行结果:两种方法都调用了 createNewEmployee() 方法

    
    -----orElse----
    ==========创建一个新对象====
    -----orElseGet----
    ==========创建一个新对象====
    
        //不同之处
        @Test
        public void test08(){
            //传入对象都不为null时
            Employee e = new Employee("默认姓名", 20, 1000);
            Optional<Employee> op = Optional.ofNullable(e);
            System.out.println("-----orElse----");
            Employee em = op.orElse(createNewEmployee());
            System.out.println("-----orElseGet----");
            Employee em1 = op.orElseGet(() -> createNewEmployee());
        }
    
    

    运行结果,只有一个方法调用了createNewEmployee()

    -----orElse----
    ==========创建一个新对象====
    -----orElseGet----
    

    这个例子说明,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。

    在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。

    4. 转换值

    4.1 map(Function f)

    若有值则对其处理,并返回处理后的Optional,否则返回Optional.empty()。

        @Test
        public void test09(){
    
            String str = Optional.ofNullable(new Employee())
                    .map(Employee::getName).orElse("张三");
            System.out.println(str);//打印输出张三
            Employee e = new Employee("默认姓名", 20, 1000);
            String str2 = Optional.ofNullable(e)
                    .map(Employee::getName).orElse("张三");
            System.out.println(str2);//打印输出默认姓名
    
        }
    

    4.2 flatMap(Function mapper)

    与map类似,但要求返回值必须是Optional。

        @Test
        public void test10(){
            Employee em = new Employee("默认姓名", 20, 1000);
    
            //map
            Optional<String> s1 = Optional.ofNullable(em)
                    .map(Employee::getName);
            System.out.println(s1);
            //flatMap  要求返回的是Optional  避免空指针
            Optional<String> s2 = Optional.ofNullable(em)
                    .flatMap(e -> Optional.of(e.getName()));
            System.out.println(s2);
    
        }
    

    5. 过滤值

    除了转换值之外,Optional 类也提供了按条件“过滤”值的方法。

    5.1 filter()

    filter() 接收一个Predicate参数,返回测试结果为true的值,如果测试结果为false,会返回一个空的Optional。

        @Test
        public void test11(){
    
            //map
            Optional<Employee> employee = Optional.ofNullable(new Employee())
                    .filter(e -> e.getName() != null);
            System.out.println(employee);//返回一个空的Optional  Optional.empty
            Employee em = new Employee("默认姓名", 20, 1000);
    
            Optional<Employee> employee1 = Optional.ofNullable(em)
                    .filter(e -> e.getName() != null);
            System.out.println(employee1);//Optional[Employee{name='默认姓名', age=20, salary=1000.0}]
    
        }
    

    如果通过过滤器测试,result 对象会包含非空值。

    三、总结

    Optional类其实就是一个封装了一个元素的容器,而这个元素可以是null也可以是其它任意类型的。Optional是Java语言的有益补充,它旨在减少代码中的NullPointerExceptions,虽然不能完全消除这些异常,他也是精心设计,自然融入了Java8函数式支持的功能

  • 相关阅读:
    【转】shell脚本中echo显示内容带颜色的实现方法
    升级到windows10之后的骚操作,安装debian,centos7,支持linux、docker、kubectl命令
    【转】Gradle的使用教程
    【转】.net core开发windows服务
    是时候抛弃Postman了,试试直接在 VS Code上调试并共享你的REST API调用
    Qt-开发环境中的代码中文显示正常,但是运行后是乱码?
    Qt-QMenu的自定义内容-在右击列表中增加一个EDIT框
    2020年十一自驾出行大攻略
    OSG-使用VS2019编译整个源代码方法
    VS2019注册码
  • 原文地址:https://www.cnblogs.com/cathyqq/p/14547147.html
Copyright © 2011-2022 走看看