似乎 C/C++ 的编程人员相比于 Java 更偏爱于断言,JDK 1.4 才开始引入 assert 的支持,但默认是关闭的,需要用 -ea
编译选项打开,否则代码中的 assert
语句全被忽略,一般会在单元测试中开启该选项。简单回顾一下 JDK 自带的断言,它用两种写法
assert object != null;
assert object != null : "object can't be null";
第一个参数是个 bool 值,断言失败只会笼统的抛出 java.lang.AssertionError
异常,并不区分是在检验方法参数还是中间运算结果。严谨来说我们会希望参数检查不通过时抛出 java.lang.IllegalArgumentException
; 而中间运算结果的断言不过希望抛出 java.lang.AssertionError
, 最好是 java.lang.IllegalStateException
。
很多时候我们不会去使用 -ea
编译选项,也就是主动放弃了 JDK 本身的断言功能。介于两个因素(不同的断言错误和默认的断言选项关闭),Scala 为我们提供了更方便的参数检查与断言方法,它们来自于 Predef , 其所定义的方法可以直接使用
require()
方法用在对参数的检验上,不通过则抛出 IllegalArgumentException
assert()
或 assume()
方法在对中间结果或私有方法的参数进行检验,不成功则抛出 AssertionError
异常,至于是用 assert()
或是 assume()
方法,就各取所好了,Scala 给出的原则如下:
本文原始链接 http://unmi.cc/scala-parameter-check-and-assertion/ , 来自隔叶黄莺 Unmi Blog
This method differs from assert only in the intent expressed: assert contains a predicate which needs to be proven, while assume contains an axiom for a static checker
说的是 assert()
包含一下需证明的条件, assume()
代表的是一个公理性的论断。
下面是一个简单的应用示例:
def foo(who: String): Unit = { require(who != null, "who can't be null") val id = findId(who) assert(id != null) //or assume(id != null, "can't find id by: " + who) }
上面可以看出,由于这些方法是定义在 Predef
中的,而 Predef
对象的方法默认是被静态引入了的,所以无需写成 Predef.require()
这样子。