千家信息网

如何使用Java Optional类

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要讲解了"如何使用Java Optional类",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用Java Optional类"吧!注意:
千家信息网最后更新 2026年11月02日如何使用Java Optional类

这篇文章主要讲解了"如何使用Java Optional类",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用Java Optional类"吧!

注意:示例代码要求使用Java 11及更高版本。所有代码在 Vavr0.10.2环境下完成测试。

Java Optional 简介

Optional 并不是什么新概念,像 Haskell、Scala 这样的函数式编程语言已经提供了实现。调用方法后,返回值未知或者不存在(比如 null)的情况下,用 Optional 处理非常好用。下面通过实例进行介绍。

新建 Optional 实例

首先,需要获得 Optional 实例,有以下几种方法可以新建 Optional 实例。不仅如此,还可以创建empty Optional。方法一,通过 value 创建,过程非常简单:

Optional four = Optional.of(Integer.valueOf(4));
if (four.isPresent){
System.out.println("Hoorayy! We have a value");
} else {
System.out.println("No value");
}

为Integer 4 新建一个Optional实例。这种方法得到的 Optional 始终包含一个 value 且不为 null,例如上面这个示例。使用 ifPresent() 可以检查value是否存在。可以注意到 four 不是 Integer,而是一个装有整数的容器。如果确认 value 存在,可以用 get() 方法执行拆箱操作。具有讽刺意味的是,调用 get() 前如果不进行检查,可能会抛出 NoSuchElementException。

方法二,得到 Optional 对象的另一种方法是使用 stream。Stream提供的一些方法会返回Optional,可以用来检查结果是否存在,例如:

  • findAny

  • findFirst

  • max

  • min

  • reduce

查看下面的代码段:

Optional car = cars.stream().filter(car->car.getId().equalsIgnoreCase(id)).findFirst();

方法三,使用 Nullable 新建 Optional。可能产生 null:

Optional nullable = Optional.ofNullable(client.getRequestData());

最后,可以新建一个 empty Optional:

Optional nothing = Optional.empty();

如何使用 Optional

获得 Optional 对象后即可使用。一种典型的场景是在 Spring 仓库中根据 Id 查找记录。可以使用 Optional 实现代码逻辑,避免 null 检查(顺便提一下,Spring 也支持 Vavr Option)。比如,从图书仓库里查找一本书。

Optional book = repository.findOne("some id");

首先,如果有这本书,可以继续执行对应的业务逻辑。在前面的章节用 if-else实现了功能。当然,还有其他办法:Optional 提供了一个方法,接收 Consumer 对象作为输入:

repository.findOne("some id").ifPresent(book -> System.out.println(book));

还可以直接使用方法引用,看起来更简单:

repository.findOne("some id").ifPresent(System.out::println);

如果仓库中没有该书,可以用ifPresentOrElseGet提供回调函数:

repository.findOne("some id").ifPresentOrElseGet(book->{
// 如果 value 存在
}, ()->{
// 如果 value 不存在
});

如果结果不存在,可以返回另一个value:

Book result = repository.findOne("some id").orElse(defaultBook);

但是,Optional 也有缺点,使用时需要注意。最后一个例子中,"确保"无论如何都能获得一本书,可能在仓库中,也可能来自 orElse。但如果默认的返回值不是常量或者需要支持一些复杂方法该怎么办?首先,Java 无论如何都会执行 findOne,然后调用 orElse方法。默认返回值可以为常量,但正如我之前所说那样,执行过程比较耗时。

另一个示例

下面用一个简单的示例介绍如何实际使用 Optional 和 Option 类。有一个 CarRepository,可以根据提供的 ID(比如车牌号)查找汽车,接下来用这个示例介绍如何使用 Optional 和 Option。

首先,加入下面代码

从 POJO 类 Car 开始。它遵循 immutable 模式,所有字段都标记为 final,只包含 getter 没有 setter。初始化时提供所有数据:

public class Car {
private final String name;
private final String id;
private final String color;
public Car (String name, String id, String color){
this.name = name;
this.id = id;
this.color = color;
}
public String getId(){
return id;
}
public String getColor() {
return color;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Car "+name+" with license id "+id+" and of color "+color;
}
}

接下来创建 CarRepository类。提供两种方法根据Id查找汽车:一种是老办法,使用 Optional。和之前在 Spring 仓库的做法类似,结果可能为 null。

publicclass CarRepository {
private List cars;
public CarRepository(){
getSomeCars();
}
Car findCarById(String id){
for (Car car: cars){function(){ //外汇跟单www.gendan5.com if (car.getId().equalsIgnoreCase(id)){
return car;
}
}
return null;
}
Optional findCarByIdWithOptional(String id){
return cars.stream().filter(car->car.getId().equalsIgnoreCase(id)).findFirst();
}
private void getSomeCars(){
cars = new ArrayList<>();
cars.add(new Car("tesla", "1A9 4321", "red"));
cars.add(new Car("volkswagen", "2B1 1292", "blue"));
cars.add(new Car("skoda", "5C9 9984", "green"));
cars.add(new Car("audi", "8E4 4321", "silver"));
cars.add(new Car("mercedes", "3B4 5555", "black"));
cars.add(new Car("seat", "6U5 3123", "white"));
}
}

注意:初始化过程会在仓库中添加一些汽车模拟数据,便于演示。为了突出重点,避免问题复杂化,下面的讨论专注于 Optional 和 Option。

使用Java Optional

使用JUnit创建一个新测试:

@Test
void getCarById(){
Car car = repository.findCarById("1A9 4321");
Assertions.assertNotNull(car);
Car nullCar = repository.findCarById("M 432 KT");
Assertions.assertThrows(NullPointerException.class, ()->{
if (nullCar == null){
throw new NullPointerException();
}
});
}

上面的代码段采用了之前的老办法。查找捷克牌照1A9 4321对应的汽车,检查该车是否存在。输入俄罗斯车牌找不到对应的汽车,因为仓库中只有捷克车。结果为 null 可能会抛出 NullPointerException。

接下来用Java Optional。第一步,获得 Optional 实例,从存储库中使用指定方法返回 Optional:

@Test
void getCarByIdWithOptional(){
Optional tesla = repository.findCarByIdWithOptional("1A9 4321");
tesla.ifPresent(System.out::println);
}

这时调用findCarByIdWithOptional方法打印车辆信息(如果有的话)。运行程序,得到以下结果:

Car tesla with license id 1A9 4321 and of color red

但是,如果代码中没有特定方法该怎么办?这种情况可以从方法返回可能包含 null 的 Optional,称为nullable。

Optional nothing = Optional.ofNullable(repository.findCarById("5T1 0965"));
Assertions.assertThrows(NoSuchElementException.class, ()->{
Car car = nothing.orElseThrow(()->new NoSuchElementException());
});

上面这段代码段中,我们发现了另一种方法。通过 findCarById 创建 Optional,如果未找到汽车可以返回 null。没有找到车牌号5T1 0965汽车时,可以用 orElseThrow 手动抛出 NoSuchElementException。另一种情况,如果请求的数据不在仓库中,可以用orElse返回默认值:

Car audi = repository.findCarByIdWithOptional("8E4 4311")
.orElse(new Car("audi", "1W3 4212", "yellow"));
if (audi.getColor().equalsIgnoreCase("silver")){
System.out.println("We have silver audi in garage!");
} else {
System.out.println("Sorry, there is no silver audi, but we called you a taxi");
}

好的,车库里没有找到银色奥迪,只好打车了!

使用 Vavr Option

Vavr OptionOption提供了另一种解决办法。首先,在项目中添加依赖,(使用 Maven)安装 Vavr:


io.vavr
vavr
0.10.2

简而言之,Vavr 提供了类似的 API 新建 Option 实例。可以从 nullable 新建 Option 实例,像下面这样:

Option nothing = Option.of(repository.findCarById("T 543 KK"));

也可以用 none 静态方法创建一个empty容器:

Option nullable = Option.none();

此外,还有一种方法可以用 Java Optional 新建 Option。看下面这段代码:

Option result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));

使用 Vavr Option,可以使用与 Optional相同的 API 来完成上述任务。例如,设置默认值:

Option result = Option.ofOptional(repository.findCarByIdWithOptional("5C9 9984"));
Car skoda = result.getOrElse(new Car("skoda", "5E2 4232", "pink"));
System.out.println(skoda);

或者,请求的数据不存在时可以抛出异常:

Option nullable = Option.none();
Assertions.assertThrows(NoSuchElementException.class, ()->{
nullable.getOrElseThrow(()->new NoSuchElementException());
});

另外,当数据不可用时,可以执行以下操作:

nullable.onEmpty(()->{
///runnable
});

如何根据数据是否存在来执行相应操作,类似 Optional 中 ifPresent?有几种实现方式。与 Optional 中 isPresent 类似,在 Option 中对应的方法称为 isDefined:

if (result.isDefined()){
// 实现功能
}

然而,使用 Option能摆脱 if-else。是否可以用Optional相同的方式完成?使用 peek 操作:

result.peek(val -> System.out.println(val)).onEmpty(() -> System.out.println("Result is missed"));

此外,Vavr Option还提供了一些其他非常有用的方法,在函数式编程上比Optional类效果更好。因此,建议您花一些时间来探索 Vavr Option javadocs尝试使用这些API。我会持续跟进一些类似 map、narrow、isLazy 和 when 这样有趣的功能。

感谢各位的阅读,以上就是"如何使用Java Optional类"的内容了,经过本文的学习后,相信大家对如何使用Java Optional类这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

方法 代码 仓库 实例 汽车 数据 示例 结果 检查 情况 接下来 函数 功能 对象 车牌 过程 面的 学习 复杂 相同 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 喔噻互联网科技有限公司 国智互联网科技 互联网 的科技创新 北京禾田雨橡互联网科技 齐家互联网科技有限公司 互联网高科技企业 互联网金融科技委员会 海南购全球互联网科技 广西拼得多互联网科技有限公司 全球顶尖互联网科技公司 成都铂石互联网科技做什么的 福建科技产业互联网发展 银川新华互联网科技学校联系电话 中国互联网公司排名锤子科技 中科明德北京互联网科技 伊宁互联网科技做什么的 锡山区互联网智能科技产品供应 深圳无忧互联网科技 富国互联网金融科技混合基金 恒生科技指数 中概互联网 西安纸贵互联网科技有限公司 互联网科技金融公司 远信互联网科技 湖北码尼互联网科技有限公司电话 河南住房之家互联网科技 企晟互联网信息科技有限公司 恒生互联网科技业指数调整周期 互联网科技实习生岗位 万物互联网智能科技 科技互联网企业在行动
0