简介
在 Java 里,Optional是 Java 8 引入的类,其目的在于解决NullPointerException问题,更优雅地处理可能为null的值。下面为你详细介绍它的用法、常见操作以及注意事项。
1. 创建 Optional 对象
- **Optional.of(value):**当确定值不为null时使用,若值为null会抛出NullPointerException。
String name = "Alice";
Optional<String> optName = Optional.of(name); // 正常创建
- **Optional.ofNullable(value):**当值可能为null时使用,若值为null会创建一个空的Optional。
String nullableName = null;
Optional<String> optNullableName = Optional.ofNullable(nullableName); // 安全创建空 Optional
- **Optional.empty():**直接创建一个空的Optional对象。
Optional<String> emptyOpt = Optional.empty(); // 空 Optional
2. 判断值是否存在
- **isPresent():**若值存在则返回true,否则返回false。
Optional<String> opt = Optional.of("Hello");
if (opt.isPresent()) {
System.out.println("值存在");
}
- isEmpty()(Java 11 及以后版本):若值不存在则返回true,否则返回false。
Optional<String> opt = Optional.empty();
if (opt.isEmpty()) {
System.out.println("值不存在");
}
- **ifPresent(Consumer):**当值存在时执行传入的操作,否则不进行任何操作。
opt.ifPresent(name -> System.out.println("姓名:" + name));
3. 获取值
- **get():**获取值,不过若值不存在会抛出NoSuchElementException,所以使用前要先通过isPresent()判断。
if (opt.isPresent()) {
String value = opt.get();
}
- **orElse(T other):**若值存在则返回该值,若不存在则返回指定的默认值。
String result = opt.orElse("默认值");
` orElseGet(Supplier<? extends T> other):若值存在则返回该值,若不存在则通过Supplier生成默认值。
String result = opt.orElseGet(() -> "通过 Supplier 生成的默认值");
- orElseThrow()(Java 10 及以后版本):若值不存在则抛出NoSuchElementException,也可以传入自定义异常。
String result = opt.orElseThrow();
// 自定义异常
String result = opt.orElseThrow(() -> new IllegalArgumentException("值不存在"));
4. 转换值
- **map(Function):**若值存在,就对其执行映射函数,否则返回空的Optional。
Optional<Integer> lengthOpt = opt.map(String::length);
- **flatMap(Function<? super T, Optional>):**与map类似,但要求映射函数返回Optional,可用于处理嵌套的Optional。
Optional<String> nestedOpt = Optional.of("text");
Optional<Character> firstChar = nestedOpt.flatMap(s ->
!s.isEmpty() ? Optional.of(s.charAt(0)) : Optional.empty()
);
5. 过滤值
**filter(Predicate):**若值存在且满足断言条件,则返回包含该值的Optional,否则返回空的Optional。
Optional<String> longName = opt.filter(name -> name.length() > 5);
示例代码
下面是一个综合示例,展示了Optional的常见用法:
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
// 创建 Optional
Optional<String> nameOpt = Optional.of("John Doe");
Optional<String> emptyOpt = Optional.empty();
// 判断值是否存在
System.out.println("nameOpt 是否存在值: " + nameOpt.isPresent()); // true
System.out.println("emptyOpt 是否存在值: " + emptyOpt.isPresent()); // false
// 获取值
String name = nameOpt.orElse("匿名");
String defaultName = emptyOpt.orElse("默认名称");
System.out.println("name: " + name); // John Doe
System.out.println("defaultName: " + defaultName); // 默认名称
// 转换值
Optional<Integer> lengthOpt = nameOpt.map(String::length);
System.out.println("姓名长度: " + lengthOpt.orElse(0)); // 8
// 过滤值
Optional<String> longNameOpt = nameOpt.filter(n -> n.length() > 5);
System.out.println("长姓名: " + longNameOpt.orElse("短姓名")); // John Doe
// 处理可能为 null 的外部调用结果
String nullableValue = getNullableValue();
Optional.ofNullable(nullableValue) //生成一个Optional对象,如果nulllableValue 为null 返回 empty Optional,否则生成一个正常值的 Optional
.ifPresentOrElse( //两个参数,如果存在怎执行第一个,如果不存在,则执行第二个。
val -> System.out.println("处理值: " + val),
() -> System.out.println("值为 null,执行默认操作")
);
}
private static String getNullableValue() {
// 模拟可能返回 null 的方法
return Math.random() > 0.5 ? "非空值" : null;
}
}
注意事项
- 避免滥用:Optional主要用于方法返回类型,以此明确表明可能没有返回值,而不是在类字段或者方法参数中使用。
- 不要直接调用get():在调用get()之前,一定要先通过isPresent()进行检查,或者使用orElse()、orElseGet()等方法。
- 不适合序列化:Optional没有实现Serializable接口,所以不要在需要序列化的类中使用它作为字段。
- 替代if-else空值检查:借助Optional的方法,可以减少代码中的空值检查逻辑,让代码更加简洁。
总结
Optional为 Java 提供了一种更安全、更优雅的方式来处理可能为null的值,降低了NullPointerException的风险,使代码更加清晰和健壮。不过,要正确使用它,避免过度包装或者错误使用导致的问题。