Java Optional 为什么不温不火?

62 阅读2分钟

Optional

Optional是JDK8新引进的一个应对null的流式api

Optional和stream流同时加入,但是现在stream流大火,而Optional鲜有使用,为什么呢?

一开始我是不怎么喜欢用Optional的,当时我认为Optional方法长,不美观,感觉不如==null

但是公司项目在使用可能空值是强制使用Optional(可能leader是rust粉丝?),接手项目后我发现Optional真香

函数返回值

我们组的规范是:

  • 函数返回值可能是null的,强制用Optional包裹
  • 对于必须返回非空的返回值,如果result==null,抛出对应异常

Optional大量使用的好处就是:强制判空,提醒了我们哪里需要判空,减少了冗余判空和漏判的发生。

举个常见的例子

应用中我们经常要获取用户Id。项目封装两个方法

public static Optional<Long> getUserIdOpt(){
    return Optional.ofNullable(id);
}
public static long getUserId(){
    return getUserIdOpt().orElseThrow(UserNotLoginException::new);
}

这两个方法对比就很明显,当用户未登录时id=null,用getUserIdOpt获取的值可能为空就要用Optional封装

外部数据

对于从外部获取(sql/nosql/rpc)的返回值,使用时需要用判空或用Optional包裹,下面给出例子

    public static void main(String[] args) {
        //get user
        User user = rpcGetUser().orElseThrow(new RpcException());
        //get email
        String email = Optional.ofNullable(user.getEmail()).orElse("");
    }
    public static Optional<User> rpcGetUser(){
        //...
        return Optional.ofNullable(user);
    }

但是真的解决问题了吗

Optional对于判空一个多变量的对象似乎很无力。

一个对象里面如果有很多字段,并且这些字段都有可能为空

这时我们要使用这些字段,就都要用Optional包装,这其实已经和==null没什么区别了

除非我们用Optional当参数?但是这是不可行的

  1. Optional当参数,本身需要判空
  2. Optional序列化问题
    public static void func(Optional<User> userOpt){
        if(userOpt != null && userOpt.isPresent()){
            //not null
        }
    }

所以Optional不是万能的,它可以帮助我们在方法的出参进行包装校验, 但是在类对象的属性判空,方法传参,类属性使用并不理想。我想这可能就是Optional不火的原因之一吧