(二)Optional

概述

        在编写代码的时候出现最多的就是空指针异常。所以在很多情况下我们需要做各种非空的判断。JDK8中引入了Optional,使用Optional可以更优雅的避免空指针异常;

1.三种创建Optional对象方式

        Optional就好像是包装类,可以把我们的具体数据封装到Optional对象内部。然后我们去使用Optional中封装好的方法操作封装进去的数据就可以优雅的避免空指针异常;

1.1.Optional.ofNullable(T value)

        Optional.ofNullable(T value)

        此方式无论封装对象是否为null,在封装为Optional对象时都不会有空指针问题;

推荐方式

  /**
     * Optional.ofNullable(T value)
     */
    public static void test1(){
        Author author = null;
        // 使用Optional.ofNullable(T value)将任意类型转为Optional对象【*推荐*,此方式将任意对象转为Optional对象时无空指针问题】
        Optional<Author> optionalAuthor = Optional.ofNullable(author);

        // 消费Optional中的数据; ifPresent()不为null则消费Optional中的数据
        optionalAuthor.ifPresent(author1 -> System.out.println(author1.getName()));
    }

1.2.Optional.of(T value)

        Optional.of(T value)

        封装对象若为null,调用Optional.of(T value)方法会出现空指针(当封装对象必定不为null时可使用此方法将封装对象转换为Optional);

 /**
     * Optional.of(T value)
     */
    public static void test2(){
        Author author = null;
        // 封装对象若为null,调用Optional.of(T value)方法会出现空指针
        Optional<Author> optionalAuthor = Optional.of(author);
    }

1.3.Optional.empty()

        Optional.empty()

        返回一个空的Optional对象;

    /**
     * Optional.empty()
     */
    private static void test3() {
        // 返回一个空的Optional对象
        Optional<Object> optional = Optional.empty();
    }

2.安全的消费Optional中值

        获取到一个Optional对象后肯定需要对其中的数据进行使用。这时候我们可以使用ifPresent方法来消费其中的值。这个方法会判断其内封装的数据是否为空,不为空时才会执行具体的消费代码;

        ifPresent(Consumer<? super T> consumer)

        内部封装数据不为null时才进行消费;

    private static void test4() {
        Author authorOne = null;
        Author authorTwo = new Author();
               authorTwo.setName("张三");

        // authorOne对象为null故使用ifPresent方法时不会执行具体的消费代码
        Optional<Author> optionalAuthor = Optional.ofNullable(authorOne);
        optionalAuthor.ifPresent(author -> System.out.println(author.getName()));

        // authorTwo对象不为null故使用ifPresent方法时会执行具体的消费代码
        Optional<Author> optionalAuthor2 = Optional.ofNullable(authorTwo);
        optionalAuthor2.ifPresent(author -> System.out.println(author.getName()));
    }

3.安全的获取Optional中值

        学习安全获取Optional中值时先了解一种不安全的获取值方式get()方法;

 /**
     * 不安全的获取Optional中值
     *      get()方法
     */
    private static void test5() {
        Optional<String> optional = Optional.ofNullable(null);
        // 不安全的获取值,当Optional中值为null时调用get方法会抛出 NoSuchElementException异常
        String result = optional.get();
    }

3.1.orElseGet

        orElseGet(Supplier<? extends T> other)

        获取数据并设置数据为null时的默认值。如果数据不为null就获取该数据。为null则返回设置的默认值;

    /**
     *  安全获取值
     *      orElseGet
     */
    private static void test6() {
        // Optional中值为null时(获取到设置的默认值)
        Optional<String> optionalOne = Optional.ofNullable(null);
        String result = optionalOne.orElseGet(() -> "默认值一");
        System.out.println(result); // 输出:默认值一

        // Optional中值不为null时(获取Optional中设置的值)
        Optional<String> optionalTwo = Optional.ofNullable("你好!");
        String result2 = optionalTwo.orElseGet(() -> "默认值二");
        System.out.println(result2); // 输出:你好!
    }

3.2.orElseThrow

        orElseThrow(Supplier<? extends X> exceptionSupplier)

        获取Optional中值为null时抛出我们自定义的异常,反之Optional中值不为null时就获取其Optional中具体的值;

    /**
     * 安全获取值
     *      orElseThrow
     */
    private static void test7() throws Throwable {
        // Optional中值不为null时获取Optional中设置的值
        Optional<String> optionalOne = Optional.ofNullable("你好!");
        String resultOne = optionalOne.orElseThrow((Supplier<Throwable>) () -> new RuntimeException("获取值为null!"));
        System.out.println(resultOne);

        // Optional中值为null时抛出我们自定义的异常
        Optional<String> optionalTwo = Optional.ofNullable(null);
        String resultTwo = optionalTwo.orElseThrow((Supplier<Throwable>) () -> new RuntimeException("获取值为null!"));
    }

4.filter函数过滤存放在Optional中数据

        使用filter方法对Optional中数据进行过滤;

例:

        使用filter方法过滤Optional对象中封装的Author对象数据;

    /**
     * filter函数过滤Optional中数据
     *      使用filter方法过滤Optional对象中封装的Author对象
     *
     *      方法最后输出:
     *          作者:张学友年龄大于18岁!
     */
    private static void test8() {
        // 创建Author对象
        Author author = new Author(1L,"张学友",60,"香港歌手",null);
        // Author对象包装为Optional对象
        Optional<Author> optionalAuthor = Optional.ofNullable(author);

        // 调用Optional对象的filter方法过滤数据
        optionalAuthor = optionalAuthor.filter(author1 -> author1.getAge() > 18);
        // 过滤后的数据调用ifPresent方法判断Optional对象中是否存在数据(存在则打印author对象)
        optionalAuthor.ifPresent(authorObj -> System.out.println("作者:" + authorObj.getName() + "年龄大于18岁!")); // 会输出


        // 调用Optional对象的filter方法过滤数据
        optionalAuthor = optionalAuthor.filter(author1 -> author1.getAge() > 88);
        // 过滤后的数据调用ifPresent方法判断Optional对象中是否存在数据(存在则打印author对象)
        optionalAuthor.ifPresent(authorObj2 -> System.out.println("作者:" + authorObj2.getName() + "年龄大于88岁!")); // 不会输出
    }

5.isPresent函数判断Optional中是否存在数据

        使用isPresent方法判断Optional中是否存在数据。为空返回false非空返回true。相较于ifPresent方法更推荐使用ifPresent方法;

推荐ifPresent方法原因:

        使用ifPresent的好处在于该方法内部会自行判断Optional对象中是否有数据,有数据才会执行后续操作;无数据则不执行后续消费操作;不像上面的isPresent方法拿取到返回值后还需程序员自行判断Optional对象中是否有数据,根据判断结果再执行后续消费代码;

    /**
     * isPresent函数判断Optional对象中是否存在数据
     *      存在:true
     *      不存在:false
     */
    private static void test9() {
        // 创建Author对象
        Author author = new Author(1L,"张学友",60,"香港歌手",null);
        // Author对象包装为Optional对象
        Optional<Author> optionalAuthor = Optional.ofNullable(author);

        /** isPresent方法使用演示 */
        boolean flag = optionalAuthor.isPresent();
        if(flag){ // Optional中存在数据
            System.out.println("Optional中存在数据!");
            // 因为上面使用isPresent方法已经判断Optional对象中已经存在数据,所以此处使用get方法获取里面的数据不会出现NoSuchElementException异常
            Author authorObj = optionalAuthor.get();
            System.out.println(authorObj);
        }else { // Optional中不存在数据
            System.out.println("Optional中不存在数据!");
        }


        /**
         * ifPresent方法使用演示
         *      使用ifPresent的好处在于该方法内部会自行判断Optional对象中是否有数据,有数据才会执行后续操作;无数据则不执行后续消费操作;
         *      不像上面的isPresent方法拿取到返回值后还需程序员自行判断Optional对象中是否有数据,根据判断结果再执行后续消费代码;
         * */
        optionalAuthor.ifPresent(author1 -> System.out.println("ifPresent方法输出的Author数据:" + author1));
    }

6.map函数对Optional中数据进行数据转换

        Optional提供了map可以对数据进行转换,并且转换得到的数据也还是被Optional包装好的;

例:

        获取作家的书籍集合;

    /**
     * map函数将Optional对象中Author数据转换为书籍集合;
     */
    private static void test10() {
        // 创建Author对象
        Author author = new Author(1L,"张学友",60,"香港歌手",null);
        // 构造作者书籍集合
        List<Book> books = new ArrayList<Book>();
                   books.add(new Book(1L, "刀的两侧是光明与黑暗", "哲学,爱情", 88, "用—把刀划分了爱恨"));
        author.setBooks(books);

        // 将Author对象包装为Optional对象
        Optional<Author> optionalAuthor = Optional.ofNullable(author);
        // map方法将原本Optional对象中的Author对象转换为Book集合(map方法返回的仍是一个Optional对象)
        Optional<List<Book>> optionalBookList = optionalAuthor.map(author1 -> author1.getBooks());
        // optionalBookList中存在数据则将其数据打印出来
        optionalBookList.ifPresent(books1 -> System.out.println(books1));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值