Java Optional的创建,用户希望从现有值返回 Optional
,使用 Optional.of
、Optional.ofNullable
或 Optional.empty
方法。与 Java 8 新增的众多类一样,Optional
实例也是不可变的(immutable)。
Java Optional的创建 问题描述
用户希望从现有值返回 Optional
。
Java Optional的创建 解决方案
使用 Optional.of
、Optional.ofNullable
或 Optional.empty
方法。
Java Optional的创建 具体实例
与 Java 8 新增的众多类一样,Optional
实例也是不可变的(immutable)。API 将 Optional
称为基于值的类(value-based class),即 Optional
实例:
- 被声明为
final
且是不可变 2 的(但可能包含对可变对象的引用); -
不提供公共构造函数(public constructor),因此必须采用工厂方法加以实例化;
-
具有
equals
、hashCode
与toString
的实现,这些实现是通过实例的状态计算出来的。
2有关不可变性的讨论请参见“Optional
与不可变性”注释。
Optional
与不可变性
Optional
实例是不可变的,但它包装的对象却不一定是不可变的。如果创建一个包含可变对象实例的Optional
,则仍然可以对实例进行修改,如例 6-1 所示。例 6-1
Optional
是不可变的吗?
AtomicInteger counter = new AtomicInteger();
Optional<AtomicInteger> opt = Optional.ofNullable(counter);
System.out.println(optional); // Optional[0]
counter.incrementAndGet(); ➊
System.out.println(optional); // Optional[1]
optional.get().incrementAndGet(); ➋
System.out.println(optional); // Optional[2]
optional = Optional.ofNullable(new AtomicInteger()); ➌
❶ 直接使用计数器自增
❷ 检索包含的值并自增
❸ 可以对 Optional
引用重新赋值
我们既可以通过原始引用修改包含的值,也可以在 Optional
上调用 get
以检索某个值进行修改。我们甚至可以对引用本身重新赋值,换言之,不能将不可变性与 final 混为一谈。但是,无法对 Optional
实例本身进行修改,因为不存在能执行这种操作的方法。
对“不可变”的定义略显模糊,这在 Java 中并不鲜见。Java 并未提供一种良好的内置方式来创建只能产生无法改变的对象的类。
我们可以通过静态工厂方法 empty
、of
与 ofNullable
来创建 Optional
,三者的签名如下:
static <T> Optional<T> empty()
static <T> Optional<T> of(T value)
static <T> Optional<T> ofNullable(T value)
显而易见,empty
方法将返回一个空 Optional
。如果参数为 null
,of
方法将返回一个包装指定值或抛出异常的 Optional
,其应用如例 6-2 所示。
例 6-2 通过
of
方法创建Optional
public static <T> Optional<T> createOptionalTheHardWay(T value) {
return value == null ? Optional.empty() : Optional.of(value);
}
在本例中,createOptionalTheHardWay
之所以被命名为“The Hard Way”,并非因为它难以实现,而是存在另一种更简单的方法,这就是例 6-3 所示的 ofNullable
方法。
例 6-3 通过
ofNullable
方法创建Optional
public static <T> Optional<T> createOptionalTheEasyWay(T value) {
return Optional.ofNullable(value);
}
在 Java 8 的引用实现中,ofNullable
方法的实现其实就是 createOptionalTheHardWay
中的语句:检查包含的值是否为 null
,若是,则返回一个空 Optional
,否则使用 of
方法进行包装。
此外,包装基本数据类型的 OptionalInt
、OptionalLong
与 OptionalDouble
类不能为 null
,因此三者只有 of
方法,没有 ofNullable
方法。
static OptionalInt of(int value)
static OptionalLong of(long value)
static OptionalDouble of(double value)
请注意,三个类的 getter 方法分别为 getAsInt
、getAsLong
与 getAsDouble
,而不是 getInt
、getLong
与 getDouble
。