避Null接口Optional

本文深入探讨Java8中Optional类的特性和使用方法,旨在解决空指针异常问题,提供链式编程风格,介绍构造函数、常用函数,并通过示例展示如何正确应用Optional提升代码质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)这个异常就不多说了,肯定是每个 Java 程序员都非常了解的异常。Optional 的完整路径是 java.util.Optional,使用它是为了避免代码中的 if (obj != null) { } 这样范式的代码,可以采用链式编程的风格。而且通过 Optional 中提供的 filter 方法可以判断对象是否符合条件,在符合条件的情况下才会返回,map 方法可以在返回对象前修改对象中的属性。

Optional的构造函数

Optional 的三种构造方式:Optional.of(obj), Optional.ofNullable(obj) 和明确的
Optional.empty()

Optional.of(obj):它要求传入的 obj 不能是 null 值的, 否则直接报NullPointerException 异常。
Optional.ofNullable(obj):它以一种智能的,宽容的方式来构造一个 Optional 实例。来者不拒,传 null
进到就得到 Optional.empty(),非 null 就调用 Optional.of(obj).
Optional.empty():返回一个空的 Optional 对象

Optional的常用函数

of:为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException。因此不经常用。
ofNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
isPresent:如果值存在返回true,否则返回false。
ifPresent:如果Optional实例有值则为其调用consumer,否则不做处理
get:如果Optional有值则将其返回,否则抛出NoSuchElementException。因此也不经常用。
orElse:如果有值则将其返回,否则返回指定的其它值。
orElseGet:orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
orElseThrow:如果有值则将其返回,否则抛出supplier接口创建的异常。
filter:如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
map:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
flatMap:如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。

Optional 应该怎样用

我们来看一个示例,我们不使用Optional写代码是这样的

public String getName(User user){
	if(user == null){
		return "Unknown";
	}else return user.name();
}

接着我们来改造一下上面的代码,使用Optional来改造,我们先来举一个Optional滥用,没有达到流畅的链式API,反而复杂的例子,如下

public String getName(User user){
	Optional<User> u = Optional.ofNullable(user);
	if(!u.isPresent()){
		return "Unknown";
	}else return u.get().name();
}

这样改写非但不简洁,而且其操作还是和第一段代码一样。无非就是用isPresent方法来替代原先user==null。这样的改写并不是Optional正确的用法,我们再来改写一次。

public String getName(User user){
	return Optional.ofNullable(user)
							.map(u -> u.name)
							.orElse("Unknown");
}

这样才是正确使用Optional的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。当然,我们还可以通过getter方式,对代码进行进一步缩减(前提是User要有getter方法哦),如下

String result = Optional.ofNullable(user)
	.flatMap(User::getAddress)
	.flatMap(Address::getCountry)
	.map(Country::getIsocode)
	.orElse("default");

### Java `Optional.orElseGet` 方法与 Null 的关系 当使用 `Optional<T>` 来封装可能为 `null` 的值时,`orElseGet` 提供了一种优雅的方式来提供默认值。此方法接受一个 Supplier 函数接口作为参数,在调用 `get()` 而实际值不存在(即内部持有 `null`)的情况下执行该供应商提供的逻辑来生成替代项。 对于 `Optional.orElseGet` 方法而言,其行为如下: - 如果 `Optional` 实例包含非空值,则直接返回这个存在的值; - 若实例代表的是缺失的值 (`Optional.empty`) 或者说持有的是 `null` 值,则会触发 supplier 并采用它所提供的结果代替之[^1]。 下面通过一段代码展示如何利用 `orElseGet` 处理潜在的 `null` 输入并给出相应的解释: ```java public class OptionalExample { public static void main(String[] args) { // 创建带有具体值得 Optional 对象 Optional<String> optionalValue = Optional.ofNullable("Hello"); // 使用 orElseGet 当存在有效数据时不触发 lambda 表达式 String resultWithValue = optionalValue.orElseGet(() -> "Default Value"); System.out.println(resultWithValue); // 输出 Hello // 创建含有 nullOptional 对象 Optional<String> emptyOptional = Optional.ofNullable(null); // 此处由于原始值为 null, 将会调用 Lambda 中定义的方法获得默认字符串 String defaultValueUsed = emptyOptional.orElseGet(() -> "Fallback Message"); System.out.println(defaultValueUsed); // 输出 Fallback Message } } ``` 值得注意的是,相比于简单的 `orElse` 方法,`orElseGet` 只有在确实需要的时候才会计算默认值——这可以带来性能上的优势,尤其是在默认值计算成本较高时[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值