好的,我们来系统讲解 Java 中的 Optional
,帮助你理解它的作用、学习用法,并附上实践示例。
一、Optional 的概念
Optional<T>
是 Java 8 引入的一个容器类,用来 防止 NullPointerException (NPE),表示 一个值可能存在,也可能不存在。
- 特点:
- 可以包含一个非 null 值,也可以为空(empty)。
- 提供了丰富的方法操作值而不需要显式判断 null。
- 鼓励使用函数式风格进行处理。
二、Optional 的常用创建方法
import java.util.Optional;
public class OptionalDemo {
public static void main(String[] args) {
// 1. of(T value):创建一个非 null Optional
Optional<String> opt1 = Optional.of("Hello");
// 2. ofNullable(T value):允许 null 值
Optional<String> opt2 = Optional.ofNullable(null);
// 3. empty():创建一个空 Optional
Optional<String> opt3 = Optional.empty();
}
}
三、Optional 的常用方法
方法 | 说明 |
---|---|
isPresent() | 判断值是否存在 |
ifPresent(Consumer<? super T> action) | 如果值存在,执行 action |
orElse(T other) | 值存在则返回,否则返回 other |
orElseGet(Supplier<? extends T> other) | 值存在则返回,否则执行 Supplier 获取值 |
orElseThrow(Supplier<? extends Throwable> exceptionSupplier) | 值存在则返回,否则抛异常 |
map(Function<? super T,? extends U> mapper) | 对值执行函数映射,并返回 Optional |
flatMap(Function<? super T, Optional<U>> mapper) | 对值执行函数映射,返回 Optional(避免嵌套 Optional) |
filter(Predicate<? super T> predicate) | 值存在且满足条件返回 Optional,否则返回 empty |
四、Optional 使用示例
1. 避免 NullPointerException
Optional<String> name = Optional.ofNullable(getUserName());
String result = name.orElse("Default Name");
System.out.println(result);
如果 getUserName()
返回 null,orElse
会提供默认值。
2. 使用 ifPresent
Optional<String> email = Optional.ofNullable(getUserEmail());
email.ifPresent(e -> System.out.println("Email: " + e));
只有在 email 存在时才会打印。
3. 使用 map 和 flatMap
Optional<User> userOpt = Optional.ofNullable(getUser());
String email = userOpt
.map(User::getProfile) // map 返回 Optional<Profile>
.map(Profile::getEmail) // map 返回 Optional<String>
.orElse("no-email@example.com");
System.out.println(email);
map
可以连续操作,处理可能为 null 的链式调用。- 避免了大量的 null 判断:
if (user != null && user.getProfile() != null) {
email = user.getProfile().getEmail();
} else {
email = "no-email@example.com";
}
4. 使用 filter
Optional<String> phoneOpt = Optional.ofNullable(user.getPhone());
phoneOpt.filter(p -> p.startsWith("+86"))
.ifPresent(p -> System.out.println("Chinese number: " + p));
filter
对值做条件筛选,不满足条件会返回 empty。
5. 使用 orElseThrow
Optional<User> userOpt = Optional.ofNullable(getUser());
User user = userOpt.orElseThrow(() -> new RuntimeException("User not found"));
- 如果 Optional 为空,就会抛出自定义异常。
五、Optional 的最佳实践
- 不要在集合中使用 Optional
List<Optional<T>>
不推荐。集合本身可以为空或空集合表示不存在。
- 不要把 Optional 作为方法参数
- Optional 更适合方法返回值,作为参数会增加复杂性。
- 链式调用处理多层嵌套对象
- 使用
map
+flatMap
避免嵌套 null 判断。
- 使用
- 结合 lambda 表达式提高代码可读性
ifPresent
、orElseGet
、filter
都能让代码更简洁。
六、完整示例
import java.util.Optional;
class Profile {
private String email;
public Profile(String email) { this.email = email; }
public String getEmail() { return email; }
}
class User {
private Profile profile;
public User(Profile profile) { this.profile = profile; }
public Profile getProfile() { return profile; }
}
public class OptionalExample {
public static void main(String[] args) {
User user = new User(null);
// 使用 Optional 链式调用获取邮箱
String email = Optional.ofNullable(user)
.map(User::getProfile)
.map(Profile::getEmail)
.orElse("no-email@example.com");
System.out.println(email); // 输出 no-email@example.com
}
}
- 效果:用一行代码代替多层 null 判断,清晰、可读、健壮。
总结:
Optional
是 Java 8 防止 NPE 的工具。- 它不存储 null,通过
orElse
,orElseGet
,orElseThrow
等方法处理缺省值。 - 支持函数式操作链 (
map
,flatMap
,filter
),简化嵌套对象处理。 - 最佳实践:只作为方法返回值,不用于参数或集合。
明白,我帮你画一张 Java Optional 使用流程图,可视化整个操作流程,从创建到获取值。
下面是文字版流程图说明,我会生成对应可视化图:
Java Optional 使用流程图(文字版)
开始
│
▼
创建 Optional
│
│-- of(value) → 必须非 null
│-- ofNullable(value) → 允许 null
│-- empty() → 空 Optional
│
▼
判断是否存在
│
│-- isPresent() → true/false
│-- ifPresent(Consumer) → 值存在时执行操作
│
▼
值存在时操作
│
│-- map(Function) → 对值进行转换,返回 Optional
│-- flatMap(Function) → 对值进行转换,返回 Optional(避免嵌套)
│-- filter(Predicate) → 条件判断,不满足返回 empty
│
▼
获取值
│
│-- orElse(defaultValue) → 值存在返回值,否则返回默认值
│-- orElseGet(Supplier) → 值存在返回值,否则调用 Supplier 获取
│-- orElseThrow(Supplier) → 值存在返回值,否则抛异常
│
▼
结束
发表回复