一、Optional类介绍说明
Java 8 引入的 Optional 类,是一个可以包含或不包含非空值的容器对象。它的目的是为了提供一种更优雅的方式来处理可能为 null 的值,从而避免直接使用 null 值可能引发的 NullPointerException。
Optional 类的主要特点:
1、防止 NullPointerException:使用 Optional 可以明确地要求用户在使用变量之前处理 null 情况
2、增强代码可读性:通过使用 Optional 的方法,代码的可读性和意图更加明确
3、集成到 Java 的流 API 中:Optional 类型在 Java 8 的流(Stream)操作中被广泛使用,提供了更复杂的条件查询和变换功能。
代码示例:
不使用Optional情况:
List<User> userList = new ArrayList<>();
userList.add(null);
userList.add(new User("张三", 15));
userList.add(new User("李四", 18));
userList.add(null);
userList.forEach(item -> {
if (item != null) {
System.out.println(item);
}
});
使用Optional情况:
List<User> userList = new ArrayList<>();
userList.add(null);
userList.add(new User("张三", 15));
userList.add(new User("李四", 18));
userList.add(null);
userList.forEach(item -> {
Optional<User> userOptional = Optional.ofNullable(item);
if (userOptional.isPresent()) {
System.out.println(item);
}
});
二、Java 8 中 Optional 类的主要方法
2.1、 创建 Optional 对象
1、Optional.of(T value) 方法
Optional.of(T value):创建一个包含非空值的 Optional 对象。如果传入的 value 是 null,则会立即抛出 NullPointerException。这个方法用于包装那些确定不为 null 的值。
Optional<String> opt = Optional.of("Hello");
Optional<String> optNull = Optional.of(null); // 会报空指针异常
2、Optional.empty() 方法
Optional.empty():创建一个空的 Optional 实例。这是用来表示没有值的情况,通常用于初始化或在条件分支中返回一个明确的“无值”状态。
Optional<String> opt = Optional.empty();
3、Optional.ofNullable(T value) 方法
Optional.ofNullable(T value):根据传入的 value 创建一个 Optional 对象。如果 value 为 null,则返回一个空的 Optional 实例;如果 value 非 null,则创建一个包含该值的 Optional 对象。这个方法用于可能为 null 的情况,提供了一种安全的方式来包装 null 值。
Optional<String> opt = Optional.ofNullable(null);
2.2、 条件动作
1、isPresent() 方法
isPresent():检查 Optional 是否包含值。如果包含值,则返回 true;否则返回 false。这个方法通常在需要基于 Optional 中是否有值来执行不同操作的场合使用。
Optional<String> opt = Optional.of("Hello");
if (opt.isPresent()) {
System.out.println("Value is present.");
} else {
System.out.println("Value is not present.");
}
2、ifPresent(Consumer<? super T> consumer) 方法
ifPresent(Consumer<? super T> consumer):如果 Optional 对象包含值,则执行给定的 consumer 操作。这个方法常用于在值存在的情况下执行某些操作,而无需进行显式的空检查。
Optional<String> opt = Optional.of("Hello");
opt.ifPresent(name -> System.out.println("Name is " + name));
2.3、 获取值动作
1、orElse(T other) 方法
orElse(T other):如果有值则返回该值,否则返回 other。这个方法用于处理 Optional 对象可能为空的情况,提供一个默认值。
String name = Optional.ofNullable(null).orElse("Default Name");
System.out.println(name); // 输出 "Default Name"
2、get() 方法
get():如果 Optional 对象包含值,则返回此值;否则抛出 NoSuchElementException。使用 get() 方法前应该先检查是否有值(例如使用 isPresent()),或者使用捕获异常的方式来处理可能的 NoSuchElementException。
Optional<String> opt = Optional.of("Hello");
if (opt.isPresent()) {
System.out.println(opt.get()); // 输出 "Hello"
} else {
System.out.println("No value present");
}
三、Optional 类使用时的注意事项
1、不要在类的字段中使用 Optional
使用 Optional 作为类的字段通常不推荐,因为 Optional 旨在作为方法的返回类型,用于有效地表示可空的结果。使用它作为字段类型会增加内存开销,同时也违反了其用作临时包装器的设计初衷。
2、避免使用 Optional 作为参数
将 Optional 用作方法参数通常是多余的。这种做法迫使调用者使用 Optional,而不是允许他们以更自然的方式传递值或 null。更好的方法是允许传递 null 并在方法内部使用 Optional.ofNullable() 进行处理。
3、不要仅为了避免 null 检查而使用 Optional
Optional 的过度使用可能导致代码质量下降,特别是当它被用来包装几乎从不为 null 的值时。它应该用在真正可能为空的情况,否则会导致不必要的复杂性。
4、避免在 Optional 上进行显式的 null 检查
Optional 的目的是为了消除代码中的 null 检查。对 Optional 对象本身进行 null 检查是没有必要的,也违背了使用 Optional 的初衷。
5、在使用 get() 方法之前总是检查是否有值
直接调用 Optional.get() 而不先检查是否有值,可能会引发 NoSuchElementException。应该使用 isPresent() 或更好的方法是 orElse(), orElseGet(), 或 orElseThrow() 等,以更安全的方式访问值。