欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OPTIONAL的一些用法

程序员文章站 2022-06-07 19:50:13
...

OPTIONAL是JAVA8带来的一个类,不知道大家是否和我一样,在一开始接触的时候,会毕竟犹豫,什么时候使用OPTIONAL,什么时候又不应该使用呢?以下是我在实际使用了一段时间之后的感受。

什么时候用OPTIONAL作为返回值?

我们大概都知道,Optional类型的对象(例如:op),我们可以使用optional.isPresent()来表达optional内实际有没有东西。如果有,我们就可以调用optional.get()方法获取其中的内容,以此来完成我们的业务逻辑。正因如此:Optional对象可以被理解为一个,可能持有东西,也可能没有的一个对象。
所以,当我们把Optional做成方法的返回值的时候,我们就可以把这个方法解读为,这个方法可能会返回对象,也可能不会。例如:

// 因为'ANDY'这个人,不一定就能查询到,所以我们返回的是一个Optional对象
Optional<User> userOptional = findOneUserByUsername("ANDY");
if (userOptional.isPresent()) {
	User user = userOptional.get();
	System.out.println(user.getAge());
	// 更多业务逻辑
}

当这个实践结合到他的反面,也就是,当一个方法,必定会返回一个对象的时候(不可能返回NULL)的时候。我们就可以按照这个约定简化代码的书写:

// 哪怕没有人,也至少可以返回一个0吧
UserCount userCount = getLatestUserCount();
//因为方法没有返回Optional,我们在这里可以不检查NULL, 直接使用其返回结果
System.out.println(userCount.getCount());
// 更多业务逻辑

我们平时在写代码的时候,有没有这样的困惑。每一个方法的返回值,我都需要检查NULL或者空的情况吗?我的原则是这样的:

  1. 对于第三方的,或者不受控的部门写的代码,最好还是都要检查,确保代码的健壮性。哪怕出错了,也能给出一个有意义的错误提醒,并且记录日志;
  2. 对于内部的API,我会采用以上的Optional的约定,并且在CodeReview和一些引导中宣贯,这会使得写代码的日子好过很多。

最后,既然方法返回值可以这样去使用,那么,传入参数是否也可以这样来操作呢?我的答案是:YES

其他常用手法

当我们手持一个Optional对象,需要获取其中的值的时候,我们除了使用optional.isPresent(),我们还能使用什么方式去获取他?其实,Optional有很多方法,可以使我们原本需要多行代码才能完成的逻辑,没有if,甚至是一行代码就可以完成。

orElse

Optional<User> userOptional = findOneUserByUsername("ANDY");
// 如果人不存在,就返回-1,代表不合法的年龄
Integer age = userOptional.map(value -> value.getAge()).orElse(-1);

关于orElse还有几个变形:

orElseGet

常常用在,我们要从数据库获取一个对象,并做更新。如果数据库里没有,我们就创建出来一个,并更新的场景

User user = findOneUserByUsername("ANDY").orElseGet(() -> {
	User newUser = new User();
	newUser.setUsername("ANDY");
	return newUser;
});

user.setAge(18);
userRepository.save(user);

orElseThrow

常常用在,我们要从数据库获取一个对象,如果数据库里没有,我们就直接报错

User user = findOneUserByUsername("ANDY")
				.orElseThrow(() -> new ApiErrorException(RESOURCE_NOT_FOUND, "用户", "ANDY"));
user.setAge(18);
userRepository.save(user);

Optional.ofNullable

这是一个很有意思的方法,面对大量的第三方依赖,如果我们也想使用以上的代码风格。可以直接使用这个方法生成一个Optional对象,哪怕其持有的对象是NULL,也没问题。这里,我经常会用这个方法,来减少无谓的if判断。例如:

// 我们以前会这么写?
Integer plus(Interge a, Interge b) {
	if (Objects.isNull(a) && Objects.isNull(b)) {
		return Integer.valueOf(0);
	}

	if (Objects.isNull(a)) {
		return b;
	}
	
	if (Objects.isNull(b)) {
		return a;
	}

	return a + b;
}

// 我们现在可以这么写,生活多美好
Integer plus(Interge a, Interge b) {
	return Optional.ofNullable(a).orElse(0) + Optional.ofNullable(b).orElse(0);
}

// 你也许会说,我可以这么写。但如果orElse换成orElseThrow呢?Optional会更加灵活
Integer plus(Interge a, Interge b) {
	return (Objects.isNull(a)? 0 : a) + (Objects.isNull(b)? 0 : b);
}

对了,这个方法有一个兄弟,是Optional.of,小心,如果传如为空的对象,会直接报错。目前我几乎没有怎么使用过它。

可以跟stream背后的一些通用方法

当组合使用Else和filter / map的时候,还是可以起到减少代码量,并且提高可读性的作用:

如果要获取一个没有被删除的用户


// 以前
User user = findOneUserByUsername("ANDY");
if (Objects.isNull(user) || user.getStatus() == "DELETED") {
	throw new ApiErrorException(RESOURCE_NOT_FOUND, "用户", "ANDY");
}
Integer age = user.getAge()
// 更多业务逻辑


// 现在
Integer age = findOneUserByUsername("ANDY")
	.filter(user -> user.getStatus() != "DELETED")
	.map(User::getAge)
	.orElseThrow(() -> new ApiErrorException(RESOURCE_NOT_FOUND, "用户", "ANDY"));

// 更多业务逻辑

那么,大家还有什么神奇的骚操作呢?

相关标签: JAVA JAVA 8 java