一次线上错误引发的事故,主角: 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了,不对...是代码。

 

 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值