Java Optional 的详解用法:告别空指针,快乐编程不再 “方”

149 阅读6分钟

嘿,各位 Java 开发者小伙伴们!今天咱要来聊聊 Java 世界里的一个超级大救星 ——Optional。这玩意儿可不得了,它的出现简直就是为了解决咱们编程过程中的一大痛点。

一、引入 Optional 的背景

在传统的 Java 编程江湖里,处理那些可能为 null 的对象,那可真是让人头疼不已。你永远不知道啥时候一个不小心,对一个 null 对象进行了方法调用,然后 “砰” 的一下,NullPointerException就蹦出来了,这就好比你走在路上突然被一块石头绊倒,不仅摔得疼,还得费好大劲爬起来找问题出在哪儿。为了拯救咱们这些苦命的程序员,Java 8 就把 Optional 这家伙给请出来啦。

二、Optional 的基本概念

Optional 呢,就像是一个神秘的小盒子。它可能里面装着一个非 null 的宝贝值,也可能啥都没有,空空如也。它的存在就是为了给咱们提供一种安全的方式来处理那些可能为 null 的值,让咱们再也不用担心直接对 null 值操作而导致的空指针异常,就像是给咱们的代码穿上了一层厚厚的铠甲。

三、创建 Optional 对象

  1. 使用 “of” 方法

    • Optional.of(T value)这个方法就像是一个有点小脾气的魔法师。你要是给它一个非 null 的值,它就开心地给你变出一个装着这个值的 Optional 对象。但是,你要是胆敢给它一个 null 值,嘿,那它可就不干了,直接给你扔出一个NullPointerException,就像在说:“嘿,别拿 null 来糊弄我!”
Optional<String> optional = Optional.of("Hello");
// 这里创建了一个包含值"Hello"Optional 对象。
  1. 使用 “ofNullable” 方法

    • 相比之下,Optional.ofNullable(T value)这个方法就温柔多啦。它可以接受一个可能为 null 的值,要是值不为 null,那就跟 “of” 方法一样变出一个 Optional 对象。要是值为 null 呢,也没关系,它就默默给你创建一个空的 Optional 对象,就像在说:“没关系,没有值咱也不发脾气。”
Optional<String> optional = Optional.ofNullable(null);
// 这里创建了一个空的 Optional 对象,因为传入的值为 null。

四、从 Optional 对象中获取值

  1. 使用 “get” 方法

    • 要是你的 Optional 对象里面有一个非 null 的值,那你就可以大胆地使用get方法来获取这个值。不过呢,你可得小心点,要是 Optional 对象是空的,你还去调用get方法,那可就惨啦,它会像一个生气的小怪兽一样扔出一个NoSuchElementException,仿佛在说:“哼,里面啥都没有,你还想拿东西?”
Optional<String> optional = Optional.of("Hello");
String value = optional.get();
// 这里 value 的值为"Hello"
  1. 使用 “orElse” 方法

    • orElse(T other)方法就像是一个贴心的小助手。如果 Optional 对象里面有值,那就把值给你。要是里面是空的呢,也没关系,它会给你一个你指定的默认值,就像在说:“别担心,没有值我给你个备胎。”
Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElse("Default");
// 这里 value 的值为"Default",因为 Optional 对象为空,所以返回了默认值。
  1. 使用 “orElseGet” 方法

    • orElseGet(Supplier<? extends T> other)方法就更高级啦。它跟 “orElse” 方法有点像,但是它接受一个Supplier函数式接口作为参数。只有在 Optional 对象为空的时候,它才会去调用这个函数来获取默认值,就像一个聪明的小精灵,知道什么时候该干活,什么时候该偷懒。
Optional<String> optional = Optional.ofNullable(null);
String value = optional.orElseGet(() -> "Generated Default");
// 这里 value 的值为"Generated Default",因为 Optional 对象为空,通过函数生成了默认值。
  1. 使用 “orElseThrow” 方法

    • orElseThrow(Supplier<? extends X> exceptionSupplier)方法就有点像一个严厉的老师。如果 Optional 对象是空的,它就会按照你给的方法扔出一个异常,让你知道你犯错误啦。就像在说:“哼,没有值还不赶紧处理,看我不惩罚你。”
Optional<String> optional = Optional.ofNullable(null);
try {
    String value = optional.orElseThrow(() -> new RuntimeException("Value is null"));
} catch (RuntimeException e) {
    System.out.println(e.getMessage());
}
// 这里会输出"Value is null",因为 Optional 对象为空,抛出了指定的异常。

五、对 Optional 对象进行操作

  1. 使用 “map” 方法

    • map(Function<? super T,? extends U> mapper)方法就像是一个神奇的变形器。它可以对 Optional 对象中包含的值进行转换。如果 Optional 对象里面有值,那就把值变个样子给你。要是里面是空的呢,那就啥也不做,就像在说:“没有东西可变,我就歇着啦。”
Optional<String> optional = Optional.of("hello");
Optional<Integer> lengthOptional = optional.map(String::length);
// 这里 lengthOptional 包含值 5,因为"hello"的长度为 5
  1. 使用 “flatMap” 方法

    • flatMap(Function<? super T,Optional<U>> mapper)方法就像是一个更厉害的变形器。它跟 “map” 方法类似,但是它接受一个函数,这个函数返回一个 Optional 对象。如果 Optional 对象里面有值,那就按照函数的要求进行变形。要是里面是空的呢,还是啥也不做。
Optional<String> optional = Optional.of("hello");
Optional<Integer> lengthOptional = optional.flatMap(s -> Optional.of(s.length()));
// 这里 lengthOptional 包含值 5,因为对"hello"进行了长度转换并返回了包含长度值的 Optional 对象。
  1. 使用 “filter” 方法

    • filter(Predicate<? super T> predicate)方法就像是一个挑剔的小管家。它可以对 Optional 对象中包含的值进行过滤。如果 Optional 对象里面有值,但是不满足过滤条件,那就给你一个空的 Optional 对象。要是里面本来就是空的,那就还是空的。就像在说:“不符合要求的别想进来。”
Optional<String> optional = Optional.of("hello");
Optional<String> filteredOptional = optional.filter(s -> s.length() > 4);
// 这里 filteredOptional 包含值"hello",因为"hello"的长度大于 4,满足过滤条件。

六、Optional 在实际项目中的应用

  1. 在方法返回值中使用 Optional

    • 当一个方法可能返回 null 值的时候,咱就可以用 Optional 作为返回类型。这样一来,调用这个方法的小伙伴们就可以清楚地知道这个返回值可能为空,然后采取相应的处理措施。就像是在给他们一个温馨提示:“嘿,这个值可能没有哦,小心点。”
public Optional<String> findUserById(int id) {
    // 查询用户逻辑,如果未找到用户则返回 null
    User user = null;
    if (user!= null) {
        return Optional.of(user.getName());
    } else {
        return Optional.empty();
    }
}
// 调用这个方法时,调用者可以根据返回的 Optional 对象来判断是否找到了用户。
  1. 在方法参数中使用 Optional

    • 方法参数也可以用 Optional 类型哦。这样就可以明确表示这个参数可能为空,让调用者更加清楚地知道该怎么处理这种情况。就像是在告诉他们:“嘿,这个参数可能没有值,你看着办吧。”
public void processUser(Optional<User> userOptional) {
    userOptional.ifPresent(user -> {
        // 处理用户逻辑
    });
}
// 调用这个方法时,可以传入一个包含用户的 Optional 对象,也可以传入一个空的 Optional 对象。

七、总结

Optional 这家伙简直就是 Java 编程世界里的大救星。有了它,咱们就可以告别那些让人头疼的空指针异常,快乐地编程,不再 “方”。在实际项目中,合理地使用 Optional 可以让咱们的代码更加清晰、易于维护。就像给咱们的代码穿上了一件漂亮的铠甲,既能保护咱们的代码不被错误攻击,又能让咱们的代码看起来更加帅气。

所以,小伙伴们,赶紧把 Optional 用起来吧,让咱们的编程之路更加顺畅!如果你们有任何问题或者建议,欢迎在评论区留言哦,让我们一起在 Java 的世界里快乐地玩耍吧!😎