Optional.ofNullable().orElse()的相关问题

817 阅读2分钟

Optional.ofNullable().orElse(),这套组合可以很优雅的对代码进行判空以及后续的处理逻辑。刚开始接触时经常使用。不过事物总是有两面性的,时间久了发现Optional有两个小问题:

  1. 问题一:ofNullable()校验不了空字符串
  2. 问题二:ofNullable()和orElse()中的逻辑都会执行,orElse()的执行并不是依赖ofNullable()中的值是否为null

问题一

public static void main(String[] args) {
    String x="";
    String s = Optional.ofNullable(x).orElse("111");
    System.out.println(s);
}

这段代码的输出结果并不是"111",而是""。看下ofNullable()的实现:

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

可见其只能用作判断null

问题二

public class Test {

    public static void main(String[] args) {
        String value = Optional.ofNullable(fetchRealValue()).orElse(defaultValue());
    }

    private static String fetchRealValue() {
        System.out.println("realValue");
        return "realValue";
    }

    private static String defaultValue() {
        System.out.println("defaultValue");
        return "defaultValue";
    }
}

上面这段代码运行后,控制台会打印出哪些内容,预期是只有"realValue",但实际上会依次打印出"realValue"和"defaultValue"。可见orElse并不会依赖ofNullable,而是始终会执行,只不过在前者为null的时候,才会去使用orElse中的结果。

代码开发中,经常会有一些场景:

  1. 某个值为null时,调一次rpc接口
  2. 某个值为null时,查一次db

类似上面这种场景,如果在使用Optional.ofNullable().orElse()时,期望当ofNullable()中的值为null时,进行兜底式的执行orElse()中的某些操作。但其实尽管前者非null,后者也会执行,这其实是对资源的浪费,尤其是orElse()中执行了某些耗时或者耗费cpu的逻辑。可以考虑吧用if...else进行优化,或者将orElse()改成orElseGet():

  • orElse 方法总是会计算默认值,无论 Optional 对象是否为空
  • orElseGet 方法只有在 Optional 对象为空时才会计算默认值,可以通过 Supplier 函数式接口提供延迟计算的能力

最后再说一句:

  • 在使用时,根据具体需求选择适合的方法。如果默认值的计算是简单的常量或已经存在的值,可以使用 orElse 方法。如果默认值的计算涉及复杂的逻辑或需要延迟计算,可以使用 orElseGet 方法。