Java的可选性并不取代所有传统的if-null-else或if-not-null-else检查
Java增加的java.util.Optional受到了欢迎,对于不能总是返回非null 值的方法,它曾带来了更流畅的代码。不幸的是,Optional被滥用了,其中一种类型的滥用是过度使用。我偶尔会遇到一些使用Optional的代码,这些代码与直接使用null 相比并没有明显的优势。
当调用代码使用Optional.ofNullable(T)来对付它刚刚调用的方法的返回值时,一个红色的标志可以提示我们,Optional 的使用比直接检查null 没有优势。就像所有的 "红旗"一样,这并不意味着将方法的返回值传递给Optional.ofNullable(T) 一定是件坏事(事实上,有必要传递给期待Optional 的API),但这种方法通常被用来提供比直接使用返回值和检查null 更多的实际价值。
在Optional可用之前,检查从一个方法返回的null ,并对null 响应采取一种行动,对非null 响应采取另一种行动的代码如下所示(这篇文章中的所有代码片段都可以在GitHub上找到):
/**
* Demonstrates approach to conditional based on {@code null} or
* not {@code null} that is traditional pre-{@link Optional} approach.
*/
public void demonstrateWithoutOptional()
{
final Object returnObject = methodPotentiallyReturningNull();
if (returnObject == null)
{
out.println("The returned Object is null.");
}
else
{
out.println("The returned object is NOT null: " + returnObject);
// code processing non-null return object goes here ...
}
}
对于这种基本条件,很少有必要涉及Optional 。下一个代码片断是我偶尔看到的代码类型的代表,当开发者试图用使用Optional来取代显式的null :
/**
* Demonstrates using {@link Optional} in exactly the manner {@code null}
* is often used (conditional on whether the returned value is empty or
* not versus on whether the returned value is {@code null} or not).
*/
public void demonstrateOptionalUsedLikeNullUsed()
{
final Optional<Object> optionalReturn
= Optional.ofNullable(methodPotentiallyReturningNull());
if (optionalReturn.isEmpty())
{
out.println("The returned Object is empty.");
}
else
{
out.println("The returned Object is NOT empty: " + optionalReturn);
// code processing non-null return object goes here ...
}
}
这段代码中的范式与传统的null-检查代码基本相同,但使用Optional.isEmpty()来执行相同的检查。这种方法没有增加任何可读性或其他优势,但确实付出了一个额外的对象实例化和方法调用的小代价。
上述使用Optional 的一个变种是将其ifPresent(Consumer)方法与isEmpty()方法结合使用,形成相同的基本逻辑,即如果返回值是存在的,就做一件事,如果返回值是空的,就做另一件事。这在下面的代码中得到了证明:
/**
* Demonstrates using {@link Optional} methods {@link Optional#ifPresent(Consumer)}
* and {@link Optional#isEmpty()} in similar manner to traditional condition based
* on {@code null} or not {@code null}.
*/
public void demonstrateOptionalIfPresentAndIsEmpty()
{
final Optional<Object> optionalReturn
= Optional.ofNullable(methodPotentiallyReturningNull());
optionalReturn.ifPresent(
(it) -> out.println("The returned Object is NOT empty: " + it));
if (optionalReturn.isEmpty())
{
out.println("The returned object is empty.");
}
}
这段代码看起来比直接检查返回值的传统方法要短一些,null ,但仍然要付出额外的对象实例化的代价,并且需要两个方法的调用。此外,首先检查Optional是否存在,然后立即检查是否为空,这感觉有点奇怪。另外,如果需要执行的逻辑比向标准输出写出一条消息更复杂,这种方法就变得不那么有效了。
结论
处理一个方法的返回值的代码,如果返回值是null ,需要做一件事,如果返回值不是 null ,需要做另一件事,那么用Optional ,简单地检查返回值是否存在或为空,很少能享受到任何好处。将方法的返回值包裹在一个Optional 中,只有在该Optional 被用于流畅链或与Optional 一起工作的API中时,才可能值得花钱。