Optional
类在 Java 8 中被引入作为一种更安全、更表达式的方法来处理可能为 null
的值。
Optional 常用方法
-
empty()
- 返回一个空的
Optional
实例。 - 用途:用于表示没有值的情况。
- 返回一个空的
-
of(T value)
- 返回包含给定非null值的
Optional
。 - 用途:当你确定变量不为
null
时使用。
- 返回包含给定非null值的
-
ofNullable(T value)
- 返回一个
Optional
,它包含了给定值,如果非null,否则返回一个空的Optional
。 - 用途:当变量可能为
null
时使用。
- 返回一个
-
get()
- 如果存在值,则返回该值,否则抛出
NoSuchElementException
。 - 用途:在确定
Optional
有值时获取它,但通常建议使用orElse
、orElseThrow
或ifPresent
等。
- 如果存在值,则返回该值,否则抛出
-
isPresent()
- 如果存在值,返回
true
,否则返回false
。 - 用途:在需要明确检查是否有值的地方用于避免
NullPointerException
。
- 如果存在值,返回
-
ifPresent(Consumer<? super T> consumer)
- 如果值存在,执行使用该值的给定操作。
- 用途:对值执行操作,例如打印或修改。
-
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
- 如果有值,执行传入的操作,没有值则执行另一个运行。
- 用途:在
Java 9
中添加。可以在值存在或不存在时执行不同操作。
-
orElse(T other)
- 如果有值则返回该值,否则返回
other
。 - 用途:提供一个默认值。
- 如果有值则返回该值,否则返回
-
orElseGet(Supplier<? extends T> other)
- 如果有值则返回该值,否则返回从
Supplier
获取的结果。 - 用途:延迟计算默认值。
- 如果有值则返回该值,否则返回从
-
orElseThrow()
- 如果有值则返回该值,否则抛出由提供的
Supplier
创建的异常。 - 用途:抛出自定义异常。
- 如果有值则返回该值,否则抛出由提供的
-
map(Function<? super T, ? extends U> mapper)
- 如果
Optional
有值,应用mapping
函数到值上。 - 用途:转换值。
- 如果
-
flatMap(Function<? super T, Optional> mapper)
- 与
map
类似,但mapper
必须返回Optional
。 - 用途:避免嵌套
Optional
(Optional<Optional<T>>
)。
- 与
-
filter(Predicate<? super T> predicate)
- 如果值存在并且符合给定的
predicate
,返回值的Optional
,否则返回空Optional
。 - 用途:条件性地过滤值。
- 如果值存在并且符合给定的
-
stream()
- 在
Java 9
中新增加。转换为可能包含或者不包含元素的Stream
。 - 用途:将
Optional
无缝集成到Stream
操作中。
- 在
示例代码
import java.util.Optional;
public class OptionalUsage {
public static void main(String[] args) {
// 创建 Optional
Optional<String> fullName = Optional.of("John Doe");
Optional<String> empty = Optional.empty();
// 检查值
if (fullName.isPresent()) {
System.out.println("Full name is set.");
}
if (empty.isEmpty()) {
System.out.println("Empty is not set.");
}
// 值存在时的操作
fullName.ifPresent(name -> System.out.println("Name: " + name));
empty.ifPresentOrElse(
name -> System.out.println("Name: " + name),
() -> System.out.println("Name is not available.")
);
// 获取值
System.out.println(fullName.get()); // John Doe
System.out.println(empty.orElse("No name")); // No name
// 转换值
Optional<String> upperName = fullName.map(String::toUpperCase);
System.out.println(upperName.orElse("No name"));
Optional<String> shortName = fullName.flatMap(name -> {
if (name.length() > 5) {
return Optional.of(name.substring(0, 5));
}
return Optional.empty();
});
System.out.println(shortName.orElse("Name too short"));
}
}
注意事项
关于 Optional
的正确使用,它并不是为了用来替代所有的 null
检查或用作所有类属性的类型。其正确的应用场景主要是作为方法的返回类型,用来清楚地表达这个方法可能返回一个值,也可能不返回值(即可能返回 null
)。例如,当一个方法查询数据库时,可能找不到所需的记录,这时返回 Optional
就能很好地表达这种可能性。
应该避免的使用场景包括:
- 不要在类的字段类型中使用
Optional
,因为这会增加类的内存占用,并且有可能违背了类的设计意图。 - 不要在方法参数中使用
Optional
,因为这会增加调用方法的复杂性。直接处理null
值通常更为清晰。 - 不要使用
Optional
来构造复杂的逻辑,比如说嵌套使用Optional
。这种情况下使用其他的逻辑控制结构更为合适,如异常处理或其他流程控制结构。