Optional.ofNullable().orElse(),这套组合可以很优雅的对代码进行判空以及后续的处理逻辑。刚开始接触时经常使用。不过事物总是有两面性的,时间久了发现Optional有两个小问题:
- 问题一:ofNullable()校验不了空字符串
- 问题二: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中的结果。
代码开发中,经常会有一些场景:
- 某个值为null时,调一次rpc接口
- 某个值为null时,查一次db
类似上面这种场景,如果在使用Optional.ofNullable().orElse()时,期望当ofNullable()中的值为null时,进行兜底式的执行orElse()中的某些操作。但其实尽管前者非null,后者也会执行,这其实是对资源的浪费,尤其是orElse()中执行了某些耗时或者耗费cpu的逻辑。可以考虑吧用if...else进行优化,或者将orElse()改成orElseGet():
- orElse 方法总是会计算默认值,无论 Optional 对象是否为空
- orElseGet 方法只有在 Optional 对象为空时才会计算默认值,可以通过 Supplier 函数式接口提供延迟计算的能力
最后再说一句:
- 在使用时,根据具体需求选择适合的方法。如果默认值的计算是简单的常量或已经存在的值,可以使用 orElse 方法。如果默认值的计算涉及复杂的逻辑或需要延迟计算,可以使用 orElseGet 方法。