Skip to content

Optional 类

为什么需要 Optional?

Optional 是 Java 8 引入的容器对象,用于表示值是否存在。

┌─────────────────────────────────────────────────────────────────┐
│                      Optional 解决的问题                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ❌ NullPointerException 是 Java 最常见的异常                     │
│  ❌ 防御性检查导致代码臃肿                                        │
│                                                                  │
│  ✅ Optional 提供了更优雅的 null 处理方式                         │
│     • 明确表示值可能为空                                         │
│     • 提供函数式操作                                              │
│     • 避免大量的 if (obj != null) 检查                           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

创建 Optional

java
// 创建空 Optional
Optional<String> empty = Optional.empty();

// 创建非空 Optional
Optional<String> present = Optional.of("Hello");

// 创建可空 Optional(推荐)
Optional<String> nullable = Optional.ofNullable(null);
Optional<String> nullable2 = Optional.ofNullable("World");

判断与获取

isPresent 与 isEmpty

java
Optional<String> opt = Optional.ofNullable("Hello");

// 判断是否有值
if (opt.isPresent()) {
    String value = opt.get();
    System.out.println(value);
}

// Java 11+ 推荐写法
if (opt.isEmpty()) {
    System.out.println("值为空");
} else {
    System.out.println(opt.get());
}

get 与 orElse

java
Optional<String> opt = Optional.ofNullable("Hello");

// 直接获取(有值返回值,无值抛异常)
String value = opt.get(); // "Hello"

// orElse - 值存在返回值,不存在返回默认值
String v1 = Optional.ofNullable("Hello").orElse("Default"); // "Hello"
String v2 = Optional.ofNullable(null).orElse("Default");     // "Default"

// orElseGet - 值存在返回值,不存在调用 Supplier 获取
String v3 = Optional.ofNullable(null).orElseGet(() -> "Generated"); // "Generated"

// orElseThrow - 值存在返回值,不存在抛出指定异常
String v4 = Optional.ofNullable(null)
    .orElseThrow(() -> new IllegalArgumentException("值不能为空"));

ifPresent

java
Optional<String> opt = Optional.ofNullable("Hello");

// 值存在时执行操作
opt.ifPresent(value -> System.out.println("值存在:" + value));

// Java 9+ ifPresentOrElse
opt.ifPresentOrElse(
    value -> System.out.println("值存在:" + value),
    () -> System.out.println("值为空")
);

链式操作

map - 转换值

java
Optional<String> opt = Optional.ofNullable("Hello");

// 值存在时转换
Optional<Integer> len = opt.map(String::length);
// len = Optional.of(5)

// 链式转换
Optional<Integer> result = Optional.ofNullable("Hello")
    .map(String::toUpperCase)
    .map(String::length);
// result = Optional.of(5)

flatMap - 避免嵌套 Optional

java
class User {
    private String name;
    private Optional<String> email;

    public Optional<String> getEmail() {
        return email;
    }
}

// ❌ 错误:使用 map 会导致嵌套 Optional
Optional<Optional<String>> nested =
    Optional.ofNullable(user).map(User::getEmail);

// ✅ 正确:使用 flatMap
Optional<String> email =
    Optional.ofNullable(user).flatMap(User::getEmail);

filter - 过滤值

java
Optional<Integer> opt = Optional.of(10);

// 值存在且满足条件才返回
Optional<Integer> filtered = opt.filter(n -> n > 5);
// filtered = Optional.of(10)

Optional<Integer> filtered2 = opt.filter(n -> n > 20);
// filtered2 = Optional.empty()

实战应用

链式查找

java
class User {
    private String name;
    private Address address;

    public Address getAddress() { return address; }
}

class Address {
    private String city;
    private Country country;

    public Country getCountry() { return country; }
}

class Country {
    private String code;

    public String getCode() { return code; }
}

// 传统写法:层层判断
public String getCountryCode(User user) {
    if (user != null) {
        Address addr = user.getAddress();
        if (addr != null) {
            Country country = addr.getCountry();
            if (country != null) {
                return country.getCode();
            }
        }
    }
    return "UNKNOWN";
}

// Optional 写法:链式调用
public String getCountryCode(User user) {
    return Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getCountry)
        .map(Country::getCode)
        .orElse("UNKNOWN");
}

集合中查找

java
List<User> users = Arrays.asList(
    new User("Tom", 25),
    new User("Jerry", 30),
    new User("Mike", 35)
);

// 查找第一个年龄大于30的用户
Optional<User> found = users.stream()
    .filter(u -> u.getAge() > 30)
    .findFirst();

// 安全获取
String name = users.stream()
    .filter(u -> u.getAge() > 30)
    .findFirst()
    .map(User::getName)
    .orElse("Not Found");

空值默认值

java
// 简单默认值
String name = Optional.ofNullable(user)
    .map(User::getName)
    .orElse("Anonymous");

// 复杂默认值
String city = Optional.ofNullable(user)
    .flatMap(User::getAddress)
    .map(Address::getCity)
    .orElseGet(() -> {
        // 复杂的默认值计算逻辑
        return lookupDefaultCity();
    });

高级用法

or 方法(Java 9+)

java
// 值不存在时,返回另一个 Optional
Optional<String> opt1 = Optional.ofNullable(null);
Optional<String> opt2 = Optional.ofNullable("Hello");

Optional<String> result = opt1.or(() -> opt2);
// result = Optional.of("Hello")

stream 方法(Java 9+)

java
// Optional 转 Stream
Optional<String> opt = Optional.ofNullable("Hello");

long count = opt.stream()
    .map(String::toUpperCase)
    .count(); // 1

// 过滤集合中的空值
List<String> names = Arrays.asList("Tom", null, "Jerry", null, "Mike");
List<String> validNames = names.stream()
    .flatMap(Optional::ofNullable)
    .collect(Collectors.toList());
// ["Tom", "Jerry", "Mike"]

ifPresentOrElse(Java 9+)

java
Optional<String> opt = Optional.ofNullable("Hello");

opt.ifPresentOrElse(
    value -> System.out.println("值: " + value),
    () -> System.out.println("值为空")
);

常见错误

┌─────────────────────────────────────────────────────────────────┐
│                      Optional 使用误区                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ❌ 不要用 Optional 替代方法参数                                  │
│     void method(Optional<String> param)  // 不推荐               │
│     void method(String param)            // 推荐,null 可接受     │
│                                                                  │
│  ❌ 不要用 Optional 替代字段                                     │
│     class User { Optional<String> name; }  // 不推荐             │
│     class User { String name; }             // 推荐               │
│                                                                  │
│  ❌ 不要过度使用 Optional                                         │
│     Optional.ofNullable(x).get()  // 多此一举                    │
│     x  // 直接使用即可                                           │
│                                                                  │
│  ✅ 正确场景:                                                   │
│     方法返回值可能为空时                                           │
│     链式处理可能为空的值时                                         │
│     集合查找结果                          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

总结

Optional 核心知识点

方法说明
ofNullable()创建可空 Optional(推荐)
isPresent()判断是否有值
get()获取值(无值抛异常)
orElse()获取值或默认值
orElseGet()获取值或调用 Supplier
map()转换值
flatMap()转换值(避免嵌套)
filter()过滤值
ifPresent()值存在时执行

⚠️ 易错点提醒

  1. 不要用 Optional 作为字段类型
  2. 不要用 Optional 作为方法参数
  3. map 和 flatMap 的区别:flatMap 避免嵌套
  4. of(null) 会抛 NullPointerException,用 ofNullable
  5. Optional 主要用于方法返回值,不适合过度使用