Optional其实就是Java的一个monad的实现。不要被monad这个词吓到 它只是一个封装来处理一个类型的具体情况 – 在这种情况下,一个空值的可能性。只要认为它是一个包装,强制用户检查值是否存在。
当以声明方式使用Optional时,我们可以在其上执行映射函数。只有在Optional中填充了一个值,才会执行与map function一起提供的lambda。
运行该 execute()方法时,控制台输出显然是:
only run if optional is filled
如果我们将maybeString的代码更改为 Optional.empty()
并再次执行,如预期的那样,没有任何反应。
但是当我们想要当Optional是null的时候的判断流程,我们可以选择 else(), elseGet(), 和 elseThrow()。最后一个,我们可以抛出一个Exception,但是如果我们想要做一些不同的事情呢?
下面的代码看起来很直观点。
通过阅读代码,我们可能期望newString会给出值, “foo” 因为 maybeString是一个包含值的可选项。 运行该 execute()
方法时,以下输出将在控制台中结束:
only run if optional is filled
only run if empty
foo
我们仍然可以得出这样的结论: newString的值最终会变成null。另一件我们可以看到的是,字符串“only run if empty”也被打印到控制台。所以即使Optional包含一个值,里面的 orElse()方法仍然在执行中。
当我们改变 execute()方法而orElseGet()不是使用方法 时 orElse(), 我们还需要将方法调用更改runIfEmpty()
的方法为:
现在我们运行execute()方法,我们看到以下内容:
only run if optional is filled
foo
在使用这个实现时,我们看到里面的方法 orElseGet()没有被执行。这是我们所希望看到的。
当我们只是使用映射为变量赋值时,您在使用orElse()来代替原来的判断流程中不会有任何问题 。你只需要确保里面的代码 orElse()是完全没有副作用的。
另一方面,如果你需要基于一个可选的引导行为,例如当用户没有找到时创建一个新的用户,你应该使用这个 orElseGet()构造。不管可选的值如何,你可能都不希望你的替代流程被执行。
在函数式编程的过程中,当你实际执行代码时,你只能看到结果。所以当然,我现在可以主张编写正确的测试代码(而且你应该),但是最好事先知道它的区别。这个差别是微妙的,但是如果你不小心的话,会产生很大的影响。