Assert使用的一个坑

简介

Assert 断言,如果不经常使用,的确觉得这个概念有点难用,断言?什么意思,即便是知道意思,刚开始用着也不顺手,不过用久了,就觉得挺顺手的。Assert和我们通常的if条件判断相反,if是如果xxx,就yyy,而Assert大概意思是:我断言xxx,如果不xxx,我就yyy(并不准确,后面会解释)。举个例子,前端参数验证


	// if验证
	if (StringUtils.isEmpty(reqVo.getUsername())) {
        throw new RuntimeException("用户名不能为空!");
    }
	
	// Assert验证
	Assert.isTrue(!StringUtils.isEmpty(reqVo.getUsername()),"用户名不能为空!")
	// 或者更简单常用的
	Assert.hasText(reqVo.getUsername(),"用户名不能为空!")
        

if翻译过来的意思是:如果用户名是空,那我就报错。而Assert是,断言用户名不为空,为空我就报错(或者 断言用户名有文本值,没有就报错)。从代码层面上来看,if要占三行,Assert一行,所以Assert更简洁,也很直观。只是刚接触的人,会觉得有点绕。

我最开始用的时候,也觉得很不习惯,和我以前用的if思维,如果xx就xx很不一样,有点排斥。不过在做前端参数验证的时候,如果用if去判断,的确代码看起来很臃肿,所以慢慢接受了Assert,感觉还挺好用的。但是我昨天在项目中使用的时候,碰到了一个坑,由于无法在本地调式,需要发版到dev调试,同事封装的工具错误提示也不友好,导致我耽误了小半天时间。

Excel表格导入数据验证,其实就是类似新增的电话号码验重,我是这么写的
我的代码大概意思是:根据电话号码去数据库查询,查询出一个实体集合,如果集合不为空,那么就说明重复了,抛出异常,并且提示:联系电话重复。
YesNoEnum.YesNoCodeNumberEnum.NO.getCode() 其实是一个枚举常量,值为Integer类型的0。第一行就是去数据库里根据电话号码查询列表,第二行就是用Assert,断言集合为空,不为空就抛出,并且把重复的那个实体信息打印出来。(以下横线之间的内容为扩展内容,可忽略)

—————————————————————————————————————

为什么只打印第一个呢?因为电话号码是唯一的(并没有在物理表上加唯一约束),所以如果在正常的业务情况下,重复只能重复一个,所以集合里面肯定只有一个记录。
那可能有小伙伴会问了,如果是这样,那你为什么要查询出来一个集合呢?直接用

this.lambdaQuery()
    .eq(KeypersonEntity::getKeypersonPhone, importVo.getKeypersonPhone()).one()

查询出一个实体,如果实体不为空,即可确定是重复了。这是我考虑到,因为数据库中并没有添加唯一约束,所以,在开发测试的时候,可能有人不走业务的添加逻辑来进行添加,而是直接操作数据库来添加,那么可能存在数据库中就存在两条及以上电话重复的数据,如果用 .one()查询,那么就会直接报错。所以我用了 .list() ,用列表来判断,能处理多个重复和一条重复的情况,都不会报错。
——————————————————————————————————————

为什么会有坑呢?按照我的逻辑,如果repetition这个集合不为空,才会抛出异常,取出集合中的第一个元素。但是Assert的运行机制并不是这样,实际上就算集合为空,Assert还是会执行一遍后面的语句,只是不会抛出异常。所以我的问题就出来了,在正常情况下,电话号码没有重复,repetition为空集合,Assert还是会去取集合中的元素,就会抛出数组下标越界异常。
多说一句,其实这是一个小问题,应该可以很快定位才对。但是,问题就是这是Excel表格导入数据时的校验,而表格导入不能直接在本地测试,需要在前端配置好之后,在dev环境里面调试,无法打断点调试。而且导入用的是同事写好的模块,抛出异常之后的提示极其不友好,在dev环境的页面上只提示了一句:数据校验异常,数组下标越界:size为0,index为0。而且我不知他们把把日志存储在哪里的。我仔细的检查我的数据校验逻辑,但是始终没有发现问题,因为我用到集合的地方都进行非空判断了。最后没有办法,找到日志的数据库,找到异常堆栈信息,才知道是Assert的坑。

ps: 推而广之,不止是Assert的isTrue方法有这个问题,其他的isNull、notNull、hasText都有这个问题(我测试过)。另外,我用的是Spring中的Assert(org.springframework.util.Assert),我测试另一个工具提供的Assert也存在同样的情况,但我不知道其它的Assert有没有这个情况,我估计都有。

总结

为什么会出现这个问题呢?我反思

  1. 对Assert没有深入了解,最开始我自己没有用Assert的,只是看到项目上的同事在用,觉得还挺顺手,简洁,所以就用了。
  2. 固有思维,受java中 短路于(双于 &&) 短路或(双或||) 的影响,还有把Assert看做了if的反向,认为Assert是,xxx,如果不就yyy,其实并不是这样,就算xxx满足了,yyy还是会执行一半,只是不会抛出异常。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值