本文目录导读:

在Java中,Optional 类的主要目的是为了避免繁琐的 null 检查,并更优雅地处理可能为 null 的值,以下是一些典型的 Java 案例,展示了 Optional 类的常见用法。
基础创建与取值
场景:避免直接返回 null,而是返回一个 Optional。
import java.util.Optional;
public class OptionalBasicExample {
public static void main(String[] args) {
// 1. 创建 Optional
Optional<String> nonEmpty = Optional.of("Hello");
Optional<String> empty = Optional.empty();
// 2. 取值:如果为空,则用默认值
String value1 = nonEmpty.orElse("Default");
String value2 = empty.orElse("Default");
System.out.println(value1); // Hello
System.out.println(value2); // Default
// 3. 取值:使用供应商函数提供默认值(懒加载)
String value3 = empty.orElseGet(() -> "Generated Default");
System.out.println(value3); // Generated Default
// 4. 取值:如果为空则抛出异常
// String value4 = empty.orElseThrow(() -> new RuntimeException("Value is absent"));
// 5. 安全检查:如果存在则执行
nonEmpty.ifPresent(val -> System.out.println("Found: " + val)); // Found: Hello
empty.ifPresent(val -> System.out.println("不会执行")); // 不会输出
}
}
链式操作与转换
场景:将 Optional 进行映射、过滤和扁平化处理。
import java.util.Optional;
public class OptionalChainingExample {
public static void main(String[] args) {
Optional<String> original = Optional.of(" Hello World ");
// 链式调用:过滤、映射、取值
String result = original
.map(String::trim) // 去除首尾空格
.filter(s -> s.length() > 5) // 长度大于5才保留
.map(String::toUpperCase) // 转大写
.orElse("TOO_SHORT");
System.out.println(result); // HELLO WORLD
// 过滤条件不满足的情况
Optional<String> shortStr = Optional.of("Hi");
String result2 = shortStr
.map(String::trim)
.filter(s -> s.length() > 5) // 长度不大于5,过滤掉
.map(String::toUpperCase)
.orElse("TOO_SHORT");
System.out.println(result2); // TOO_SHORT
}
}
避免空指针异常 —— 传统 vs Optional
场景:从深层嵌套的对象中获取属性(如 user.getAddress().getCity()),传统方式需要大量判空,而 Optional 可以优雅地处理。
import java.util.Optional;
class Address {
private String city;
public Address(String city) { this.city = city; }
public String getCity() { return city; }
}
class User {
private Address address;
public User(Address address) { this.address = address; }
public Optional<Address> getAddress() { return Optional.ofNullable(address); }
}
public class OptionalNullSafeExample {
public static void main(String[] args) {
// 用户有地址
User userWithAddress = new User(new Address("Beijing"));
// 用户没有地址
User userWithoutAddress = new User(null);
// 1. 传统方式(易出错)
String cityTraditional = "Unknown";
if (userWithAddress.getAddress().isPresent()) {
cityTraditional = userWithAddress.getAddress().get().getCity();
}
System.out.println(cityTraditional); // Beijing
// 2. 使用 Optional 链式调用(推荐)
String city = Optional.ofNullable(userWithAddress)
.flatMap(User::getAddress)
.map(Address::getCity)
.orElse("Unknown");
System.out.println(city); // Beijing
// 3. 对于没有地址的用户
String city2 = Optional.ofNullable(userWithoutAddress)
.flatMap(User::getAddress)
.map(Address::getCity)
.orElse("Unknown");
System.out.println(city2); // Unknown (不会报空指针)
}
}
结合流(Stream)使用
场景:从集合中查找元素,结果可能为空,用 Optional 处理查找结果。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class OptionalWithStreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 查找名字长度大于5的第一个
Optional<String> firstLongName = names.stream()
.filter(name -> name.length() > 5)
.findFirst();
// 处理结果
firstLongName.ifPresent(name -> System.out.println("Long name: " + name)); // Charlie
// 查找名字长度大于10的(不存在)
Optional<String> none = names.stream()
.filter(name -> name.length() > 10)
.findFirst();
// 如果不存在,使用 orElse 提供默认值
String result = none.orElse("No name longer than 10 chars");
System.out.println(result); // No name longer than 10 chars
}
}
在方法返回值中使用(推荐模式)
场景:在自定义方法中,用 Optional 表示可能没有返回值,让调用方明确知道需要处理空的情况。
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class OptionalReturnExample {
private static Map<Integer, String> database = new HashMap<>();
static {
database.put(1, "Apple");
database.put(2, "Banana");
}
// 查询用户,可能找不到
public static Optional<String> findUserById(int id) {
return Optional.ofNullable(database.get(id));
}
public static void main(String[] args) {
// 调用方必须处理 Optional
Optional<String> user1 = findUserById(1);
user1.ifPresent(System.out::println); // Apple
Optional<String> user3 = findUserById(3);
String name = user3.orElse("Guest");
System.out.println(name); // Guest
// 建议调用方保持 Optional 链式风格:
String uppercaseName = findUserById(1)
.map(String::toUpperCase)
.orElseThrow(() -> new RuntimeException("User not found"));
System.out.println(uppercaseName); // APPLE
}
}
使用 ifPresentOrElse (Java 9+)
场景:当值存在时执行一个操作,不存在时执行另一个操作。
import java.util.Optional;
public class IfPresentOrElseExample {
public static void main(String[] args) {
Optional<String> val = Optional.of("Hello");
// Java 9+ 支持
val.ifPresentOrElse(
s -> System.out.println("Value: " + s),
() -> System.out.println("No value")
); // 输出: Value: Hello
Optional<String> empty = Optional.empty();
empty.ifPresentOrElse(
s -> System.out.println("Value: " + s),
() -> System.out.println("No value")
); // 输出: No value
}
}
| 场景 | 推荐方法 |
|---|---|
| 避免 null 返回值 | 返回 Optional<T> 代替 T |
| 安全获取嵌套属性 | flatMap + map + orElse |
| 提供默认值 | orElse(value) / orElseGet(Supplier) |
| 存在时执行操作 | ifPresent(Consumer) |
| 不存在时抛出异常 | orElseThrow(Supplier) |
| 与流结合使用 | findFirst() / findAny() 返回 Optional |
⚠️ 注意:不要对 Optional 使用 .get() 而不先检查 isPresent(),这仍然可能抛出 NoSuchElementException,建议始终使用 orElse、orElseGet 等安全方法。