【Java】Optional 类全面详解,告别空指针异常

大家好,最近在复盘 Java 基础知识点,发现很多小伙伴依旧会被空指针异常(NullPointerException) 困扰。从 Java 8 开始,官方推出了 Optional 工具类,它的核心作用就是优雅地处理空值,从根源上规避空指针问题。今天这篇文章,我就带大家完整梳理 Optional 的使用方式,搭配实战代码,一起来学习吧。

一、认识 Optional 与创建对象

Optional 是一个容器类,可以存放单个值,这个值可以是非空,也可以是。它一共提供了三种常用方式来创建实例,不同方法适用场景不同,大家一定要区分清楚。

1. empty ():创建空的 Optional 对象

如果我们需要一个不包含任何值的 Optional,直接调用静态方法 empty() 即可。

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

2. of ():创建非空 Optional 对象

of() 方法要求传入的参数绝对不能为 null,一旦传入空值,会直接抛出空指针异常。适合我们明确知道数据一定不为空的场景。

// 传入非空字符串,正常创建对象
Optional<String> opt = Optional.of("云扬");

// 下面这行代码会直接抛出 NullPointerException
// Optional<String> errorOpt = Optional.of(null);

3. ofNullable ():兼容空与非空(最常用)

这是日常开发中使用最多的方法。它可以接收 null 和非空值,参数为空时等价于 empty(),不为空则和 of() 效果一致,通用性最强。

String name1 = "Java学习";
String name2 = null;

// 非空值
Optional<String> opt1 = Optional.ofNullable(name1);
// 空值
Optional<String> opt2 = Optional.ofNullable(name2);

二、判断 Optional 中是否存在值

拿到 Optional 对象后,我们首先需要判断内部是否存有有效值,这里有两组方法可以使用。

1. isPresent ():判断值是否存在

如果容器内有值,返回 true;值为 null,返回 false。Java 8 及以上版本均支持。

Optional<String> opt = Optional.of("云扬");
Optional<String> nullOpt = Optional.ofNullable(null);

// 输出 true
System.out.println(opt.isPresent());
// 输出 false
System.out.println(nullOpt.isPresent());

2. isEmpty ():判断值是否为空

该方法是 Java 11 新增的,作用和 isPresent() 完全相反,用来判断容器是否为空。

Optional<String> opt = Optional.of("云扬");
Optional<String> nullOpt = Optional.ofNullable(null);

// 输出 false
System.out.println(opt.isEmpty());
// 输出 true
System.out.println(nullOpt.isEmpty());

三、函数式处理值:ifPresent 系列方法

Optional 结合了函数式编程思想,ifPresent 系列方法可以简化空值判断后的业务逻辑,替代传统的 if (obj != null) 写法。

1. ifPresent ():值存在则执行逻辑

Optional 中有值时,执行传入的 Lambda 表达式;为空则不执行任何操作。

Optional<String> opt = Optional.of("云扬");
// 值存在,执行打印字符串长度
opt.ifPresent(str -> System.out.println("字符串长度:" + str.length()));

2. ifPresentOrElse ():Java 9 新增,双分支逻辑

这是 Java 9 推出的增强方法,接收两个参数:值存在执行第一个逻辑,值为空则执行第二个逻辑,完美实现「存在则处理,不存在则兜底」。

Optional<String> opt = Optional.ofNullable(null);
opt.ifPresentOrElse(
    str -> System.out.println("值为:" + str),
    () -> System.out.println("Optional 为空")
);

四、设置默认值,优雅获取数据

很多场景下,当 Optional 为空时,我们需要返回一个默认值,这里主要使用 orElse()orElseGet() 两个方法。

1. orElse()

无论 Optional 是否为空,默认值都会提前创建。为空时返回设定的默认值,不为空则返回原有值。

String userName = null;
// userName 为 null,返回默认值 "默认用户名"
String result = Optional.ofNullable(userName).orElse("默认用户名");
System.out.println(result);

2. orElseGet()

参数为一个函数式接口,只有当 Optional 为空时,才会执行函数生成默认值,性能优于 orElse(),推荐优先使用。

String userName = null;
String result = Optional.ofNullable(userName)
        .orElseGet(() -> "默认用户名");
System.out.println(result);

补充:get () 方法(不推荐使用)

get() 可以直接获取容器内的值,但如果 Optional 为空,会抛出 NoSuchElementException 异常,失去了 Optional 防空指针的意义,日常开发尽量避免使用。

Optional<String> opt = Optional.of("云扬");
// 正常取值
System.out.println(opt.get());

五、过滤值:filter () 方法

filter() 接收一个断言函数式接口 Predicate,可以按照自定义条件过滤 Optional 中的值:

  • 满足条件:返回原 Optional 对象;
  • 不满足条件 / 原对象为空:返回空的 Optional

常用来做数据筛选、条件校验。

// 筛选长度大于 3 的字符串
Optional<String> opt = Optional.of("Java编程");
Optional<String> filterOpt = opt.filter(str -> str.length() > 3);
filterOpt.ifPresent(System.out::println);

六、转换值:map () 方法

如果我们需要对 Optional 内部的值进行类型转换、数据加工,可以使用 map() 方法。它会对值进行处理,并封装成新的 Optional 对象返回。

// 将字符串转为大写,并重新封装为 Optional
Optional<String> opt = Optional.of("yunyang");
Optional<String> upperOpt = opt.map(String::toUpperCase);
upperOpt.ifPresent(System.out::println);

总结

Optional 并不是用来完全替代 null,而是提供一套规范、优雅的空值处理方案。在实际开发中,我给大家几个小建议:

  1. 创建对象优先使用 ofNullable(),兼容性最强;
  2. 获取值优先使用 orElseGet(),少用 get()
  3. 结合 ifPresentfiltermap 链式编程,简化代码;
  4. 合理利用版本特性,Java 9+ 可以使用 ifPresentOrElse,Java 11+ 可用 isEmpty

掌握好 Optional,能大幅减少项目中的空指针异常,让代码更加健壮。后续我也会持续更新 Java、MySQL、Linux 等后端技术内容,大家可以持续关注~

Tags:

发表回复

Your email address will not be published. Required fields are marked *.

*
*