一次线上错误引发的事故,主角: java.util.NoSuchElementException: No value present
背景
今天无意间使用一个没什么太大用的功能点时,突然我的小美不停的给我发消息...
别误会,小美不是“人”,是机器人,诺~就是下面这货!
根据小美的提示找到代码位置,一看,我傻了,这么取值,不是写BUG吗?
VAllCustomer customer = vAllCustomerRepository.findById(consume.getCustomerId()).get();
我们可以看到IDEA都有提示:SonarLint: Call "Optional#isPresent()" before accessing the value.
说人话就是:就是用get的调用主体时查询不到、为空,就会报No value present 异常问题,需要我们在get()前先调用isPresent()进行非空判断。
一说到非空...不得不想到臭名昭著的NPE异常(NullPointerException),空指针。这货也是我们java程序员职业生涯中遇到最多的一个异常了。简直深恶痛绝..
在我们平常使用中,我相信大多数的人非空判断无非如下:
ConsumeIntegral consumeIntegral = consumeIntegralRepository.findByConsumeId(consume.getId());
if (consumeIntegral != null) {
if(consumeIntegral.getIntegral()!=null){
vo.getData().setCurrentScore(consumeIntegral.getIntegral());
}
if(consumeIntegral.getTotalScore()!=null){
vo.getData().setTotalScore(consumeIntegral.getTotalScore());
}
......//这要是有三五十个参数不得要命?
}
言归正传,找一找No value present错误的来源。
首先我们先看源码,可以看到返回的是Optional,这个错误就是由Optional统一抛出来的。
VAllCustomer customer = vAllCustomerRepository.findById(consume.getCustomerId()).get();
Optional<T> findById(ID var1);
看源码
/**
* If a value is present in this {@code Optional}, returns the value,
* otherwise throws {@code NoSuchElementException}.
*
* @return the non-null value held by this {@code Optional}
* @throws NoSuchElementException if there is no value present
*
* @see Optional#isPresent()
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
可以清楚的看到源码中,如果获取的对象是null,就会统一抛出这个异常提示了。所以,在我们取值的时候一定要加上非空判断!
解决
在get()方法的下面,官方提供了一个判断的方法,我们可以直接使用。
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
Optional<SystemUser> createUser = systemUserRepository.findById(consume.getGmdUser());
if(createUser.isPresent()){
vo.getData().setCreateUser(createUser.get().getUserName());
}//感觉还是不够big
换一种方式
/**
* If a value is present, invoke the specified consumer with the value,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
ifPresent()是官方为我们提供的一个方法,已经为我们判断了空值,如果为空就不会执行后面的取值!
Optional<SystemUser> createUser = systemUserRepository.findById(consume.getGmdUser());
createUser.ifPresent(systemUser -> vo.getData().setCreateUser(systemUser.getUserName()));
再短一点
systemUserRepository.findById(consume.getGmdUser()).ifPresent(systemUser -> vo.getData().setCreateUser(systemUser.getUserName()));
结
这下小美再也不会打扰我写bug了,不对...是代码。
版权声明:本文为qq_24373533原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。