Java 什么时候用 assert,什么时候用 if

2022-06-16 14:03:17 +08:00
 dramakevinzz

第一次实习,看组里的代码有的方法进来是 assert ,有的是 if 来判断方法传入的参数是否有效。 目前对 assert 的理解是当我们 debug 或者启动时带-ea 参数的时候,会对方法传入参数进行判断,所以我理解它是在测试阶段能够进行判断。但是当项目上线的时候就无效了。 if 的话就是我们在任何时刻和阶段都可以对方法的传入参数的有效性进行判断。 现在不太确定我对 assert 和 if 的理解是否正确,以及有点不太确定什么时候用 assert ,什么时候应该用 if 。请问是否有朋友可以帮忙指点一下。

2031 次点击
所在节点    问与答
21 条回复
cheng6563
2022-06-16 14:21:59 +08:00
没用过 assert
Mirage09
2022-06-16 14:23:34 +08:00
最简单的方法,看看 git blame ,问一问作者为什么要这么写
msg7086
2022-06-16 14:24:52 +08:00
写测试的时候用 assert 。
assert 一般意味着不满足 assert 就是程序质量有问题,或者是发生了必须要立刻终止程序的严重事态(比如内存数据被篡改,等等)。

仅为个人理解。
cwm165
2022-06-16 14:28:05 +08:00
org.springframework.util.Assert

Spring 也封装过一个 assert 。 你点进源码可以看到,它就是为 if 做了一个封装。
区别于 org.junit.Assert 只是在测试代码中使用。

所以不要看到同名的类就感到疑惑,还是要看一下它的内部实现,不过这对第一次实习的朋友来说也不是大问题,以后看的多了就明白了。

至于用 assert 还是 if ,看心情,或者和团队统一,Spring assert 就是 if 的一个封装,不喜欢大段 if 那就大段 assert /doge
billlee
2022-06-16 14:28:42 +08:00
如果你相信按照设计,某个方法收到的参数必定符合某个约束,那就用 assert. 这样在开发过程中如果代码逻辑有问题违反了约束,酒就可以捕获到
falsemask
2022-06-16 14:30:59 +08:00
@cwm165 op 说的 assert 应该不是你说的 assert ,是断言 assert
dramakevinzz
2022-06-16 14:38:29 +08:00
@Mirage09 我 mentor 在 review 的时候,有的时候会把我写的 assert 改成 if ,有的时候会把 if 改成 assert ,说让我自己体会下什么时候用 assert ,什么时候用 if ,但是我没体会出来,又不是很敢打扰他,就来论坛问问各位前辈。
@msg7086 那我目前的想法时,在企业级应用中应该都是有部门来严格判断恶意用户的侵入性行为吧,那上下游服务中我们的参数真的有可能会出现严重违反规定的情况存在吗?所以就感觉 assert 不是很必要,应该都用 if 来判断,当参数无效的时候应该直接退出方法或者返回相应类型的空。不知道我的看法对不对。
@falsemask 对的,这里是指断言 assert ,我没有说清楚。
tairan2006
2022-06-16 14:48:47 +08:00
assert 代码 release 之后无效,只是用来调试的。

说白了,就是可能会有问题就 if ,一定不会出现问题(除非有 bug )就 assert.
Mirage09
2022-06-16 14:49:26 +08:00
@dramakevinzz
体会个什么玩意,传功么…
直接问他吧,不要频繁骚扰人不意味着不问问题,更何况这是你的第一个实习
msg7086
2022-06-16 15:01:39 +08:00
@dramakevinzz 哦,我也误解了,以为你说的是 JUnit 之类的 assert 。
Java 自己的 assert 断言说实话我代码读到现在还没有见人使用过。(也可能是我读得少……
liquid207
2022-06-16 15:23:36 +08:00
lzrainchen
2022-06-16 18:50:25 +08:00
Java 中的 assert 关键字中文翻译为"断言",if 关键字为"分支跳转"。这两个的确不是同一个"东西"。如果你领导真的让你思考体会,你真的应该仔细体会一下。以下是我的理解:assert 在于检测当前状态必须为某个状态,而 if 在于控制状态之间的流转。这就是他们最本质的不同。我用大白话再解释一下:程序就是一个状态机,在某一个时刻状态机只有一个确定的状态,这个时候我们可以 assert 它是一个什么状态,如果不是此状态就说明程序不符合我们的设定,可能有错。而 if 条件在于控制状态机的流转,就这样。其实我们想解释清楚一件事是很困难的哪怕再不起眼的小事。仔细思考,仔细体会
adoal
2022-06-16 19:30:58 +08:00
举个栗子:过程 A ,从界面获取用户输入;过程 B ,检查用户输入的格式正确性;过程 C ,拿用户输入调用后端业务。
业务逻辑是按顺序调用 A 、B 、C 。

过程 B 里判断输入格式是否正确,用 if ,因为不对的格式是用户输入的,程序不可控,遇到了不是程序的错。

过程 C 里要再检查一遍用 assert ,因为这里数据不是直接来自不可控的用户输入,这是程序员可控的环节,格式再不对就是 B 写错了,写对的程序执行到这里不应该有不对的数据。
liprais
2022-06-16 19:32:45 +08:00
assert 就是不符合就要 panic 不能往下走了
if 就是不符合下面还有
yolee599
2022-06-16 21:46:06 +08:00
assert 就是开发的时候使用的,上线的时候失效,可以减少对运行效率的影响,并且确保生产环境中不会出现这种问题。通常用于入参合法性判断,比如入参空指针。
litmxs
2022-06-16 22:13:58 +08:00
assert 用于内部接口,输入的数据在开发阶段可控,调用者是内部的开发者,如果不满足 assert 条件,说明是开发人员编码问题,这时候应该把整个程序都干掉,因为这是编码错误,应该要及时暴露出来。


if 用于外部接口,开发阶段没办法知道会传入什么样的数据,需要校验然后返回相应错误提示(错误码、日志、异常等),然后让程序重试或者安全退出。
sun1993
2022-06-17 10:41:47 +08:00
写 UT 的时候用 assert ,其余情况不考虑,反正我是这么干的
dramakevinzz
2022-06-17 13:21:03 +08:00
@lzrainchen
@adoal
@liprais
@yolee599
@litmxs
大致明白了,还是要结合业务场景去判断,比如上游数据应该是从内部服务中获取的,这种就应该用 assert ,因为内部服务要确保数据的合理性和正确性,但是如果对于由外部不可控因素的数据就应该是用 if ,那我再结合代码看下吧,谢谢各位
liprais
2022-06-17 13:27:27 +08:00
dramakevinzz
2022-06-18 09:13:57 +08:00
@liprais 感谢,目前有了更多理解

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/860022

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX