用Optional取代null思考

    public static String getCarInsuranceName(Person person) {
//        return person.getCar().getInsurance().getName();
        //null-安全的第一种尝试:深层质疑
        if (person != null) {
            Car car = person.getCar();
            if (car != null) {
                Insurance insurance = car.getInsurance();
                if (insurance != null) {
                    return insurance.getName();
                }
            }
        }
        return "Unknown";
    }

深层质疑”,原因是它不断重复着一种模式:每次你不确定一
个变量是否为null时,都需要添加一个进一步嵌套的if块,也增加了代码缩进的层数。很明显,
这种方式不具备扩展性,同时还牺牲了代码的可读性。

第二种尝试

        //null-安全的第二种尝试:过多的退出语句
        if (person == null) {
            return "Unknown";
        }
        Car car = person.getCar();
        if (car == null) {
            return "Unknown";
        }
        Insurance insurance = car.getInsurance();
        if (insurance == null) {
            return "Unknown";
        }
        return insurance.getName();

第二种尝试中,你试图避免深层递归的if语句块,采用了一种不同的策略: 每次你遭遇null
变量,都返回一个字符串常量“Unknown”。然而,这种方案远非理想,现在这个方法有了四个
截然不同的退出点,使得代码的维护异常艰难。更糟的是,发生null时返回的默认值,即字符
串“Unknown”在三个不同的地方重复出现——出现拼写错误的概率不小!当然,你可能会说,
我们可以用把它们抽取到一个常量中的方式避免这种问题。
使用Optional重新定义Person/Car/Insurance的数据模型

变量存在时, Optional类只是对类简单封装。变量不存在时,缺失的值会被建模成一个“空”
的Optional对象,由方法Optional.empty()返回。 Optional.empty()方法是一个静态工厂
方法,它返回Optional类的特定单一实例。你可能还有疑惑, null引用和Optional.empty()
有什么本质的区别吗?从语义上,你可以把它们当作一回事儿,但是实际中它们之间的差别非常
大 : 如 果 你 尝 试 解 引 用 一 个 null , 一 定 会 触 发 NullPointerException , 不 过 使 用
Optional.empty()就完全没事儿,它是Optional类的一个有效对象,多种场景都能调用,非
常有用。

Optional<Person> optPerson = Optional.of(person);
Optional<String> name =
optPerson.map(Person::getCar)
.map(Car::getInsurance)
.map(Insurance::getName);

不幸的是,这段代码无法通过编译。为什么呢? optPerson是Optional<Person>类型的
变量, 调用map方法应该没有问题。但getCar返回的是一个Optional<Car>类型的对象(如代
码清单10-4所示),这意味着map操作的结果是一个Optional<Optional<Car>>类型的对象。因
此,它对getInsurance的调用是非法的,因为最外层的optional对象包含了另一个optional
对象的值,而它当然不会支持getInsurance方法。

所以,我们该如何解决这个问题呢?让我们再回顾一下你刚刚在流上使用过的模式:
flatMap方法。使用流时, flatMap方法接受一个函数作为参数,这个函数的返回值是另一个流。
这个方法会应用到流中的每一个元素,最终形成一个新的流的流。但是flagMap会用流的内容替
换每个新生成的流。换句话说,由方法生成的各个流会被合并或者扁平化为一个单一的流。这里
你希望的结果其实也是类似的,但是你想要的是将两层的optional合并为一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值