java Optional类

Optional 是 Java 8 引入的一个容器类,用于表示可能为 null 的对象。它的目的是帮助开发者减少 NullPointerException,并鼓励以一种更安全和功能化的方式处理空值。

Optional 类是 java.util 包中的一部分,提供了一种更优雅的方式来处理可能为 null 的值,避免了直接对 null 进行操作或检查。

1. 创建 Optional 对象

1.1 使用 Optional.of()

Optional.of() 用于创建一个包含非 null 值的 Optional 对象。如果传入 null,它会抛出 NullPointerException

String value = "Hello, Optional!";
Optional<String> optional = Optional.of(value);

1.2 使用 Optional.ofNullable()

Optional.ofNullable() 可以接受 null,并根据传入的值生成一个 Optional 对象。如果传入的是 null,则返回一个空的 Optional 对象。

String value = null;
Optional<String> optional = Optional.ofNullable(value);  // 如果value为null,返回Optional.empty()

1.3 创建空的 Optional 对象

如果你明确知道要创建一个空的 Optional 对象,可以使用 Optional.empty()

Optional<String> emptyOptional = Optional.empty();  // 创建一个空的 Optional 对象

2. 常用方法

2.1 isPresent() 和 ifPresent()

  • isPresent():检查 Optional 中的值是否存在。
  • ifPresent():如果值存在,则执行传入的 Consumer
Optional<String> optional = Optional.of("Hello");
if (optional.isPresent()) {
    System.out.println(optional.get());  // 输出 Hello
}

// 或者使用 ifPresent 来代替 isPresent 和 get
optional.ifPresent(System.out::println);  // 输出 Hello

2.2 get()

get() 方法用于获取 Optional 中的值。如果 Optional 中没有值(即为空),它会抛出 NoSuchElementException

Optional<String> optional = Optional.of("Hello");
String value = optional.get();  // 返回 "Hello"

注意get() 方法在实际开发中不推荐频繁使用,因为它可能抛出异常。通常可以使用其他更安全的方法来处理。

2.3 orElse() 和 orElseGet()

  • orElse(T other):如果 Optional 中的值存在,则返回该值,否则返回传入的默认值。
  • orElseGet(Supplier<? extends T> other):如果 Optional 中的值存在,则返回该值,否则通过提供的 Supplier 生成并返回默认值。
Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElse("Default Value");
System.out.println(value);  // 输出 "Default Value"

String value2 = optional.orElseGet(() -> "Generated Default Value");
System.out.println(value2);  // 输出 "Generated Default Value"

2.4 orElseThrow()

orElseThrow() 方法如果 Optional 中没有值,则抛出指定的异常。

Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElseThrow(() -> new IllegalArgumentException("Value is missing"));

2.5 map() 和 flatMap()

  • map():如果 Optional 中有值,则对该值应用给定的函数,并返回一个新的 Optional
  • flatMap():与 map() 类似,但是它的返回值必须是 Optional 类型(常用于返回一个 Optional 的链式操作)。
Optional<String> optional = Optional.of("Hello");
Optional<String> mapped = optional.map(s -> s.toUpperCase());
System.out.println(mapped.get());  // 输出 "HELLO"

Optional<String> flatMapped = optional.flatMap(s -> Optional.of(s.toUpperCase()));
System.out.println(flatMapped.get());  // 输出 "HELLO"

2.6 filter()

filter() 方法允许你对 Optional 中的值进行条件过滤。如果条件满足,则返回包含该值的 Optional,否则返回空的 Optional

Optional<String> optional = Optional.of("Hello");
Optional<String> filtered = optional.filter(s -> s.startsWith("H"));
System.out.println(filtered.get());  // 输出 "Hello"

Optional<String> filteredEmpty = optional.filter(s -> s.startsWith("X"));
System.out.println(filteredEmpty.isPresent());  // 输出 false

3. Optional 使用场景

Optional 主要用于函数式编程风格的代码中,尤其适用于以下场景:

  • 避免空指针异常(NullPointerException:通过返回 Optional 类型,可以明确地表示某个值可能为空,从而避免直接使用 null
  • 链式操作:由于 Optional 提供了丰富的 API 方法(如 map()flatMap()filter()),可以方便地进行链式操作。
  • 更清晰的 API 设计:通过 Optional,可以明确表示某个返回值是可选的,而不是简单地返回 null,使 API 更具可读性和可维护性。

4. 不推荐使用场景

虽然 Optional 非常有用,但也有一些场景不适合使用 Optional

  • 存储大量对象的字段Optional 应该用于返回值,而不是类的成员变量或字段,因为它会增加额外的封装层。
  • 性能敏感的代码Optional 本质上是一个容器,它会带来一些额外的开销。如果性能是关键因素,不建议过度使用。

5. 示例代码

import java.util.Optional;

public class OptionalExample {

    public static void main(String[] args) {

        // 创建Optional对象
        Optional<String> optionalValue = Optional.of("Hello, Java");

        // 使用ifPresent方法进行操作
        optionalValue.ifPresent(value -> System.out.println("Value is present: " + value));

        // 使用orElse提供默认值
        String defaultValue = optionalValue.orElse("Default Value");
        System.out.println(defaultValue);  // 输出 "Hello, Java"

        // 使用orElseThrow抛出异常
        try {
            Optional<String> emptyOptional = Optional.ofNullable(null);
            emptyOptional.orElseThrow(() -> new IllegalArgumentException("Value not present"));
        } catch (Exception e) {
            System.out.println(e.getMessage());  // 输出 "Value not present"
        }

        // 使用map方法进行转换
        Optional<String> upperCaseOptional = optionalValue.map(String::toUpperCase);
        upperCaseOptional.ifPresent(System.out::println);  // 输出 "HELLO, JAVA"
        
        // 使用filter方法进行条件过滤
        Optional<String> filteredOptional = optionalValue.filter(s -> s.contains("Java"));
        filteredOptional.ifPresent(System.out::println);  // 输出 "Hello, Java"
    }
}

总结

Optional 是一个非常有用的工具类,可以帮助你更安全地处理 null 值,避免出现 NullPointerException。通过使用 Optional 提供的丰富方法,能够更清晰、简洁地处理可能为空的对象,并且可以链式操作。但在某些情况下,过度使用 Optional 会带来性能开销,应该根据实际需求谨慎选择使用。

上一篇:Easyexcel(3-文件导出)-写入单个Sheet


下一篇:jQuery 代码中添加注释