【Java】优雅的利用Optional进行逐层安全的解析

在Java开发的过程中,经常会遇到烦人的NullPointerException异常,为了避免NullPointerException,遇到逐层解析的场景,需要嵌套多层if else进行解析。

示例代码如下:
SchoolInfo.java

/**
 * 学校信息 SchoolInfo.java
 */
public class SchoolInfo {

    /**
     * 编码
     */
    private String code;

    /**
     * 学校名称
     */
    private String name;

    public String getCode() {
        return code;
    }

    public SchoolInfo setCode(String code) {
        this.code = code;
        return this;
    }

    public String getName() {
        return name;
    }

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

ClassInfo.java

/**
 * 班级信息 ClassInfo.java
 */
public class ClassInfo {

    /**
     * 编码
     */
    private String code;

    /**
     * 班级名称
     */
    private String name;

    /**
     * 班主任
     */
    private String teacherName;

    /**
     * 所属学校信息
     */
    private SchoolInfo schoolInfo;

    public String getCode() {
        return code;
    }

    public ClassInfo setCode(String code) {
        this.code = code;
        return this;
    }

    public String getName() {
        return name;
    }

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

    public String getTeacherName() {
        return teacherName;
    }

    public ClassInfo setTeacherName(String teacherName) {
        this.teacherName = teacherName;
        return this;
    }

    public SchoolInfo getSchoolInfo() {
        return schoolInfo;
    }

    public ClassInfo setSchoolInfo(SchoolInfo schoolInfo) {
        this.schoolInfo = schoolInfo;
        return this;
    }
}

StudentInfo.java

/**
 * 学生信息 StudentInfo.java
 */
public class StudentInfo {

    /**
     * 编码
     */
    private String code;

    /**
     * 姓名
     */
    private String name;

    /**
     * 性别
     */
    private String gender;

    /**
     * 所属班级信息
     */
    private ClassInfo classInfo;

    public String getCode() {
        return code;
    }

    public StudentInfo setCode(String code) {
        this.code = code;
        return this;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public StudentInfo setGender(String gender) {
        this.gender = gender;
        return this;
    }

    public ClassInfo getClassInfo() {
        return classInfo;
    }

    public StudentInfo setClassInfo(ClassInfo classInfo) {
        this.classInfo = classInfo;
        return this;
    }
}

开发过程中经常遇到的一个场景是:需要获取学生StudentInfo的所属学校名称School::name。在Java 7及以下版本中,我们会不得不采用以下方法进行操作:

public class TestStudent {

    public static void main(String[] args) {

        // 学校信息
        SchoolInfo schoolInfo = new SchoolInfo().setCode("HZXH07").setName("杭州测试学校");
        // 班级信息
        ClassInfo classInfo = new ClassInfo().setCode("0203").setName("高二(3)班").setSchoolInfo(schoolInfo);
        // 学生信息
        StudentInfo studentInfo = new StudentInfo().setCode("2302010").setName("Jack").setGender("Male").setClassInfo(classInfo);

        String schoolName = TestStudent.getSchoolName(studentInfo);
        System.out.println(schoolName);
    }

    /**
     * 获取学生所属学校名称
     *
     * @param studentInfo
     * @return
     */
    private static String getSchoolName(StudentInfo studentInfo) {

        String schoolName = "";
        // 避免空指针异常,先判断学生信息是否为空
        if (studentInfo != null) {
            // 再判断所属班级信息是否为空
            if (studentInfo.getClassInfo() != null) {
                // 再判断班级所属学校信息是否为空
                if (studentInfo.getClassInfo().getSchoolInfo() != null) {
                    schoolName = studentInfo.getClassInfo().getSchoolInfo().getName();
                }
            }
        }
        System.out.println(schoolName);
        return schoolName;
    }
}

上述代码中,为了避免NullPointerException异常,我们不得不用了三层if来分别判断studentInfostudentInfo.getClassInfo()studentInfo.getClassInfo().getSchoolInfo()是否为null。但凡有一层为null,都会中止下一层的判断。

优雅的使用Optional

Optional是Java8的一个新特性,官方文档对于Optional的解释如下:

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.

简单翻译一下就是

Optional是一个容器对象,可以包含也可以不包含非null值。如果值提供(非null)调用isPresent()方法会返回true ,并且 get() 方法会返回该值。

首先贴出简化后的代码:

    /**
     * 获取学生所属学校名称
     *
     * @param studentInfo
     * @return
     */
    private static String getSchoolName(StudentInfo studentInfo) {
        String schoolName = Optional.ofNullable(studentInfo).map(student -> student.getClassInfo()).map(class_ -> class_.getSchoolInfo()).map(school -> school.getName()).orElse("");
        return schoolName;
    }

可以看到,原本的三层if判断+取值操作,变成了一行的Optional.ofNullable.map().orElse(),从代码量上来说简化不少。当然上面的代码可以进一步简化为:

    private static String getSchoolName(StudentInfo studentInfo) {
        String schoolName = Optional.ofNullable(studentInfo).map(StudentInfo::getClassInfo).map(ClassInfo::getSchoolInfo).map(SchoolInfo::getName).orElse("");
        return schoolName;
    }

逻辑上这份代码与上面的代码无多大差异,只是改用了方法引用形式,在这里不展开来讲解。
我们再对Optional.ofNullable.map().orElse()展开来讲解。

  • Optional.ofNullable:Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional.如果非null,返回一个Optional 对象;否则返回一个空Optional
  • Optional.map:If a value is present, apply the provided mapping function to it, and if the result is non-null, return an Optional describing the result. Otherwise return an empty Optional.如果存在值,对其执行提供的映射函数,如果结果非null,返回结果的Optional 对象;否则返回一个空Optional
  • Optional.orElse:Return the value if present, otherwise return other. 如果存在值,则返回;否则返回给定的默认值

把上面的代码加上备注,可能更方便大家理解:


    /**
     * 获取学生所属学校名称
     *
     * @param studentInfo
     * @return
     */
    private static String getSchoolName(StudentInfo studentInfo) {
        String schoolName = Optional.ofNullable(studentInfo) // 初始化一个Optional,非空则为studentInfo对象的Optional;反之则为空Optional
                .map(StudentInfo::getClassInfo) // 对于非空Optional,执行映射方法StudentInfo::getClassInfo,结果非空则返回结果Optional,反之则返回空Optional
                .map(ClassInfo::getSchoolInfo) // 原理同上
                .map(SchoolInfo::getName) // 原理同上
                .orElse(""); // 上一步Optional为空,则返回默认值"";反之则返回上一步Optional的值
        return schoolName;
    }

可以看到,原先的三层if代码,通过Optional进行优化后,大大减少的代码量,而且从代码的角度来说,看上去也更加的优雅。

以上 : )



扩展阅读:

  1. Java stream多字段分组(groupingBy)
  2. React + Router + Antd实现多标签页功能
  3. https://blog.csdn.net/m0_58016522/article/details/127784778
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值