返回值不存在的常规处理方法
如果一个方法在调用时需要考虑值为null的情况, 此时一般的处理方法有两种:
1、如果不存在值,抛出异常。
2、方法返回null,在使用返回值之前判断 user 是否为null
但是抛出异常的开销很高,判断是否为null就必须包含特殊的代码处理null的可能性,如果客户端忽略了这种可能性,那么就会抛出NullPointerException异常。
比如用方法2编写如下方法:
import com.atlassian.jira.user.ApplicationUser
ApplicationUser getApplicationUser(boolean condition){
ApplicationUser user = null
if(condition){
user = ComponentAccessor.getUserManager().getUserByName("F20G001588");
return user
}
return user
}
boolean condition1 = true
ApplicationUser user = getApplicationUser(condition1)
user.username
如果condition1的值为false,那么返回的user就为null,执行这段代码将会报错:
Something went wrong: NullPointerException : Cannot get property 'username' on null object
用Optional<T>代替null或者抛出异常
此时就可以考虑使用Optional<T>,它最多可以包含一个元素。它本质上是一个受检异常,它强迫用户面对没有返回值的情况。而未受检的异常或者null都允许用户忽略这种可能性,从而带来灾难性的后果。
上面的方法可以改成这种形式:
import com.atlassian.jira.user.ApplicationUser
import java.util.function.Supplier
Optional<ApplicationUser> getApplicationUserOptional(boolean condition){
ApplicationUser user = null
if(condition){
user = ComponentAccessor.getUserManager().getUserByName("F20G001588");
return Optional.of(user)
}
return Optional.empty()
}
boolean condition2 = true
Optional<ApplicationUser> userOptional = getApplicationUserOptional(condition2)
其中 Optional.of() 用来返回正常值,Optional.empty() 用来代替null
Optional提供了多种处理方式处理返回结果,下面是几个较常见的方法
1、如果返回值不存在,那么提供一个默认值
//定义一个默认值
ApplicationUser defaultUser = ComponentAccessor.getUserManager().getUserByName("admin");
userOptional.orElse(defaultUser) //F20G001588(JIRAUSER10961) 或者 admin(JIRAUSER10000)
2、默认返回值放在Supplier<T>方法中,减少执行开销
上面的方式,无论值存不存在都需要执行查询默认值的方法,如果开销过大,默认值查询方法可以放在Supplier<T>中
//如果创建默认值开销大,那么就用supply<T>实现,只有在结果不存在时才查询默认值
import java.util.function.Supplier
Supplier<ApplicationUser> getDefaultUser = () -> ComponentAccessor.getUserManager().getUserByName("admin");
userOptional.orElseGet(getDefaultUser) //F20G001588(JIRAUSER10961) 或者 admin(JIRAUSER10000)\
3、返回值不存在就抛出异常
import java.util.function.Supplier
Supplier<IllegalArgumentException> exceptionSupplier = () -> new IllegalArgumentException("Optional 是空的");
userOptional.orElseThrow(exceptionSupplier); //F20G001588(JIRAUSER10961) 或者 抛出异常
另外,Optional还提供了其他特殊方法:
filter
map
flatMap
ifPresent
isPresent()
其中,isPresent()可以代替上面的所有方法
int、long、double类型的Optional
除了Optional方阿飞,实际上还有OptionalInt OptionalLong OptionalDouble多种方法,如果返回的值类型是int、long、double且可能不存在值的时候,可以使用这些方法代替Optional<T>
注重性能的代码不要使用Optional
在注重性能的代码中,最好还是返回null、或者抛出异常,因为Optional是一个必须进行分配和初始化的对象,从optional读取需要额外的开销