Java的Optional实战

一 引入Optional前的问题

1 代码

/**
* Copyright (C), 2020-2020, 软件公司
* FileName: WithoutOptionalDemo
* Author:   cakin
* Date:     2020/4/24
* Description: 没有 Optional 会有什么问题
*/
package optionaldemo;

import lombok.extern.slf4j.Slf4j;

/**
* @ClassName: WithoutOptionalDemo
* @Description: 没有 Optional 会有什么问题
* @Date: 2020/4/24
* @Author: cakin
*/
@Slf4j
public class WithoutOptionalDemo {
    class Member {
        /**
         * 名字
         */
        private String name;


        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        Member mem = getMemberByIdFromDB();
        /**
         * 问题在这里,需要判断是否为空,否则会引起NullPointerException问题
         */
        if (mem != null) {
            log.info(mem.getName());
        }
    }

    public static Member getMemberByIdFromDB() {
        // 当前 ID 的会员不存在
        return null;
    }
}

二 引入Optional解决的问题

1 代码

/**
* Copyright (C), 2020-2020, 软件公司
* FileName: OptionalDemo
* Author:   cakin
* Date:     2020/4/24
* Description: Optional 解决NullPointerException这个问题
*/
package optionaldemo;

import lombok.extern.slf4j.Slf4j;

import java.util.Optional;

/**
* @ClassName: OptionalDemo
* @Description: Optional 解决NullPointerException这个问题
* @Date: 2020/4/24
* @Author: cakin
*/
@Slf4j
public class OptionalDemo {
    public static void main( String[] args ) {
        Optional<Member> optional = getMemberByIdFromDB();
        optional.ifPresent(mem -> {
            log.info("name: " + mem.getName());
        });
    }

    public static Optional<Member> getMemberByIdFromDB() {
        boolean hasName = true;
        if (hasName) {
            return Optional.of(new Member("cakin"));
        }
        return Optional.empty();
    }
}

class Member {
    /**
     * 名字
     */
    private String name;


    public String getName() {
        return name;
    }

    Member( String name ) {
        this.name = name;
    }
}

2 测试

20:05:58.115 [main] INFO optionaldemo.OptionalDemo - name: cakin

三 Optional实战

1 代码

/**
* Copyright (C), 2020-2020, 软件公司
* FileName: OptionalTest
* Author:   cakin
* Date:     2020/4/24
* Description: Optional 用法
*/


package optionaldemo;


import common.Constant;
import lombok.extern.slf4j.Slf4j;


import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.function.Predicate;


/**
* @ClassName: OptionalTest
* @Description: Optional 用法
* @Date: 2020/4/24
* @Author: cakin
*/
@Slf4j
public class OptionalTest {
    public static void main( String[] args ) {
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");
        /**
         * 创建 Optional 对象
         */
        Optional<String> empty = Optional.empty();
        log.info("empty is " + empty);


        Optional<String> opt = Optional.of("cakin");
        log.info("opt is " + opt);


        String name = null;
        try {
            Optional<String> optnull = Optional.of(name);
        } catch (NullPointerException e) {
            log.info("catch NullPointerException");
        }


        String name1 = null;
        Optional<String> optOrNull = Optional.ofNullable(name1);
        log.info("optOrNull is" + optOrNull);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * 判断值是否存在
         */
        Optional<String> opt1 = Optional.of("cakin");
        log.info("opt1 is " + opt1.isPresent());


        Optional<String> optOrNull1 = Optional.ofNullable(null);
        log.info("optOrNull1 is " + optOrNull1.isPresent());
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * 非空表达式
         */
        Optional<String> optOrNull2 = Optional.ofNullable("cakin");
        if (optOrNull2.isPresent()) {
            log.info("optOrNull2 length is " + optOrNull2.get().length());
        }


        Optional<String> opt2 = Optional.of("cakin");
        opt2.ifPresent(str -> log.info("str length is " + str.length()));
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * orElse() :用于返回包裹在 Optional 对象中的值,如果该值不为 null,则返回;否则返回默认值。
         * 该方法的参数类型和值得类型一致。
         */
        String nullName = null;
        String name2 = Optional.ofNullable(nullName).orElse("cakin");
        log.info("name2 is " + name2);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * orElseGet() :与 orElse() 方法类似,但参数类型不同。
         * 如果 Optional 对象中的值为 null,则执行参数中的函数。
         */
        String nullName1 = null;
        String name3 = Optional.ofNullable(nullName1).orElseGet(() -> "cakin");
        log.info("name3 is " + name3);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * orElse() 方法和 orElseGet() 方法分别调用 getDefaultValue() 方法返回默认值。
         * 两者输出结果一致
         * 类名 :: 方法名是 Java 8 引入的语法,方法名后面是没有 () 的,表明该方法并不一定会被调用。
         */
        String name4 = null;
        log.info("orElse");
        String name5 = Optional.ofNullable(name4).orElse(getDefaultValue());
        log.info("name5 is " + name5);


        log.info("orElseGet");
        String name6 = Optional.ofNullable(name4).orElseGet(OptionalTest::getDefaultValue);
        log.info("name6 is " + name6);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         *  Optional 对象的值不为 null,orElse() 方法和 orElseGet() 方法输出结果不一样
         *  orElseGet() 没有去调用 getDefaultValue(),性能更优
         */
        String name7 = "cakin";
        log.info("orElse");
        String name8 = Optional.ofNullable(name7).orElse(getDefaultValue());
        log.info("name8 is " + name8);


        log.info("orElseGet");
        String name9 = Optional.ofNullable(name7).orElseGet(OptionalTest::getDefaultValue);
        log.info("name9 is " + name9);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * 获取值
         * get() 方法才是最正宗的获取 Optional 对象值的方法,但很遗憾,该方法是有缺陷的,
         * 因为假如 Optional 对象的值为 null,该方法会抛出 NoSuchElementException 异常。
         * 建议 orElseGet() 方法获取 Optional 对象的值。
         */
        String name10 = null;
        Optional<String> optOrNull10 = Optional.ofNullable(name10);
        try {
            log.info(optOrNull10.get());
        } catch (NoSuchElementException e) {
            log.info("catch NoSuchElementException");
        }
        log.info(optOrNull10.orElseGet(() -> name10));
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * 过滤值 filter方法实现
         */
        String password = "12345";
        Optional<String> opt3 = Optional.ofNullable(password);
        // 由于 password 的长度为 5 ,所以程序输出的结果为 false。
        log.info("pass:" + opt3.filter(pwd -> pwd.length() > Constant.NUM6).isPresent());


        Predicate<String> len6 = pwd -> pwd.length() > Constant.NUM6;
        Predicate<String> len10 = pwd -> pwd.length() < Constant.NUM10;
        Predicate<String> containA = pwd -> pwd.contains("A");


        password = "1234567A";
        Optional<String> opt4 = Optional.ofNullable(password);
        boolean result = opt4.filter(len6.and(len10).and(containA)).isPresent();
        // 密码变成了 7 位,在 6 到 10 位之间,并且包括A,所以通过了
        log.info("pass:" + result);
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");


        /**
         * 转换值
         */
        // 名字转换为长度
        nameLength();
        // 验证密码
        validPassword();
        log.info("++++++++++++++++++++++++++++++++++++++++++++++");
    }


    /**
     * 功能描述:验证密码
     *
     * @author cakin
     * @date 2020/4/24
     */
    private static void validPassword() {
        String password = "pAssWord";
        Optional<String> opt = Optional.ofNullable(password);


        Predicate<String> len6 = pwd -> pwd.length() > Constant.NUM6;
        Predicate<String> len10 = pwd -> pwd.length() < Constant.NUM10;
        Predicate<String> eq = pwd -> pwd.equals("password");


        boolean result = opt.map(String::toLowerCase).filter(len6.and(len10).and(eq)).isPresent();
        log.info("pass:" + result);
    }


    /**
     * 功能描述:将name转成长度
     *
     * @author cakin
     * @date 2020/4/24
     */
    private static void nameLength() {
        String name = "cakin";
        Optional<String> nameOptional = Optional.of(name);
        Optional<Integer> intOpt = nameOptional
                .map(String::length);
        log.info("name length is " + intOpt.orElse(0));
    }


    public static String getDefaultValue() {
        log.info("getDefaultValue");
        return "cakin";
    }
}

2 测试

21:37:18.303 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.309 [main] INFO optionaldemo.OptionalTest - empty is Optional.empty
21:37:18.311 [main] INFO optionaldemo.OptionalTest - opt is Optional[cakin]
21:37:18.311 [main] INFO optionaldemo.OptionalTest - catch NullPointerException
21:37:18.311 [main] INFO optionaldemo.OptionalTest - optOrNull isOptional.empty
21:37:18.311 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.311 [main] INFO optionaldemo.OptionalTest - opt1 is true
21:37:18.311 [main] INFO optionaldemo.OptionalTest - optOrNull1 is false
21:37:18.311 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.311 [main] INFO optionaldemo.OptionalTest - optOrNull2 length is 5
21:37:18.375 [main] INFO optionaldemo.OptionalTest - str length is 5
21:37:18.375 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.375 [main] INFO optionaldemo.OptionalTest - name2 is cakin
21:37:18.375 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.376 [main] INFO optionaldemo.OptionalTest - name3 is cakin
21:37:18.376 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.376 [main] INFO optionaldemo.OptionalTest - orElse
21:37:18.376 [main] INFO optionaldemo.OptionalTest - getDefaultValue
21:37:18.376 [main] INFO optionaldemo.OptionalTest - name5 is cakin
21:37:18.376 [main] INFO optionaldemo.OptionalTest - orElseGet
21:37:18.376 [main] INFO optionaldemo.OptionalTest - getDefaultValue
21:37:18.376 [main] INFO optionaldemo.OptionalTest - name6 is cakin
21:37:18.376 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.376 [main] INFO optionaldemo.OptionalTest - orElse
21:37:18.376 [main] INFO optionaldemo.OptionalTest - getDefaultValue
21:37:18.376 [main] INFO optionaldemo.OptionalTest - name8 is cakin
21:37:18.377 [main] INFO optionaldemo.OptionalTest - orElseGet
21:37:18.377 [main] INFO optionaldemo.OptionalTest - name9 is cakin
21:37:18.377 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.377 [main] INFO optionaldemo.OptionalTest - catch NoSuchElementException
21:37:18.378 [main] INFO optionaldemo.OptionalTest - null
21:37:18.379 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.383 [main] INFO optionaldemo.OptionalTest - pass:false
21:37:18.389 [main] INFO optionaldemo.OptionalTest - pass:true
21:37:18.389 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++
21:37:18.391 [main] INFO optionaldemo.OptionalTest - name length is 5
21:37:18.393 [main] INFO optionaldemo.OptionalTest - pass:true
21:37:18.393 [main] INFO optionaldemo.OptionalTest - ++++++++++++++++++++++++++++++++++++++++++++++

Process finished with exit code 0

四 参考

https://blog.csdn.net/qing_gee/article/details/104767082

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值