1 -当方法可以返回null时,作为一个公共方法返回类型:
这是Optional的预期用例,如JDK API文档中所示:
Optional主要用于作为方法返回类型,其中
显然需要表示“没有结果”,并且在其中使用null
很可能造成错误。
Optional表示两种状态之一:
它有一个值(isPresent返回true)
它没有值(isEmpty返回true)
因此,如果您有一个方法返回一些东西或不返回,这就是Optional的理想用例。
这里有一个例子:
Optional<Guitarist> findByLastName(String lastName);
此方法接受一个用于在数据库中搜索实体的参数。有可能不存在这样的实体,因此使用Optional返回类型是一个好主意,因为它迫使调用该方法的人考虑空场景。这减少了出现NullPointerException的机会。
2 -当参数可以为空时,作为方法参数:
尽管在技术上是可能的,但这不是Optional的预期用例。
让我们考虑一下您提议的方法签名:
public Foo doSomething(String id, Optional<Bar> barOptional);
主要的问题是我们可以调用doSomething,其中barOptional有三种状态之一:
a可选值,例如doSomething("123",可选。(新酒吧())
可选的,例如doSomething("123", Optional.empty())
例如:doSomething("123", null)
这3种状态需要在方法实现中适当地处理。
更好的解决方案是实现重载方法。
public Foo doSomething(String id);
public Foo doSomething(String id, Bar bar);
这使得API的使用者可以非常清楚地知道调用哪个方法,并且不需要传递null。
3 -作为bean的可选成员:
给定示例Book类:
public class Book {
private List<Pages> pages;
private Optional<Index> index;
}
Optional类变量遇到了与上面讨论的Optional方法参数相同的问题。它可以有三种状态之一:存在、空或null。
其他可能的问题包括:
Serializable:如果你实现Serializable并尝试序列化这个类的对象,你会遇到java.io.NotSerializableException,因为Optional不是为这个用例设计的
转换为JSON:当序列化为JSON时,可选字段可能会以不希望的方式映射,例如{"empty":false,"present":true}。
尽管如果您使用流行的Jackson库,它确实为这个问题提供了一个解决方案。
尽管存在这些问题,Oracle还是在2014年发布Java 8 Optional时发布了这篇博文。它包含了对类变量使用Optional的代码示例。
public class Computer {
private Optional<Soundcard> soundcard;
public Optional<Soundcard> getSoundcard() { ... }
...
}
在接下来的几年里,开发人员找到了更好的替代方法,比如实现getter方法来创建Optional对象。
public class Book {
private List<Pages> pages;
private Index index;
public Optional<Index> getIndex() {
return Optional.ofNullable(index);
}
}
在这里,我们使用ofNullable方法返回一个带有值的Optional,如果index是非空的,或者返回一个空的Optional。
4 -收集:
我同意创建一个可选列表(例如List<Optional<Foo>>)不会添加任何东西。
相反,如果该项目不存在,则不要将其包含在列表中。