require
和assert
都用于在运行时执行某些检查以验证某些条件。
那么它们之间的基本区别是什么?
我看到的唯一一个是require
抛出IllegalArgumentException
和assert
抛出AssertionError
。
如何选择使用哪一个?
答案 0 :(得分:68)
如Kigyo所述,存在语义差异
还有一个主要的技术差异:
assert
注明@elidable(ASSERTION)
这意味着您可以使用-Xelide-below ASSERTION
或-Xdisable-assertions
编译程序,编译器不会生成断言的字节码。如果您有大量断言,这可以显着减少字节码大小并提高性能。
了解这一点,您可以使用assert
验证程序中所有不变量无处不在(每个方法/函数的所有前置条件/后置条件)电话)并且不支付生产价格。
您通常会进行" 测试"在启用所有断言的情况下进行构建,它会慢一些,因为它会一直验证所有断言,然后你就可以拥有" 生产"在没有断言的情况下构建您的产品,您将消除通过断言完成的所有内部状态检查
require
不是elidable,在库(包括内部库)中使用更有意义来通知调用者调用给定方法/函数的前提条件。
答案 1 :(得分:20)
这只是我的主观观点。
每当我想要参数约束时,我都会使用require
。
作为一个例子,我们可以采用自然数的阶乘。由于我们不想解决负数,我们想要抛出IllegalArgumentException
。
我会使用assert
,只要你想确保某些条件(如不变量)在执行期间始终为真。我认为这是一种测试方式。
以下是使用require
和assert
def fac(i: Int) = {
require(i >= 0, "i must be non negative") //this is for correct input
@tailrec def loop(k: Int, result: Long = 1): Long = {
assert(result == 1 || result >= k) //this is only for verification
if(k > 0) loop(k - 1, result * k) else result
}
loop(i)
}
当result > 1
为真时,循环至少执行一次。因此结果必须大于或等于k
。这将是一个循环不变量。
如果您确定自己的代码是正确的,可以删除assert
,但require
会保留。
答案 2 :(得分:2)
用非常简单的语言:
Require
用于对函数的调用者或某个类的对象的创建者强制执行前提条件。然而,assert
用于检查函数本身的代码。
因此,如果先决条件失败,那么您将获得illegal argument exception
。然而,如果断言失败并且不是调用者的错,那么你得到assertion error
。
答案 3 :(得分:1)
Scaladocs/javadocs 也很不错:
package utils
import (
"text/template"
)
type Context map[string]interface{}
type FString struct {
Data string
template *template.Template
}
func (fs *FString) MustCompile(expr string, funcMap template.FuncMap) {
fs.template = template.Must(template.New("f-string").
Funcs(funcMap).
Parse(expr))
}
func (fs *FString) Write(b []byte) (n int, err error) {
fs.Data += string(b)
return len(b), nil
}
func (fs *FString) Render(context map[string]interface{}) error {
if err := fs.template.Execute(fs, context); err != nil {
return err
}
return nil
}
func (fs *FString) MustRender(context Context) {
if err := fs.Render(context); err != nil {
panic(err)
}
}
func (fs *FString) Clear() string {
// return the data and clear it
out := fs.Data
fs.Data = ""
return out
}
Tests an expression, throwing an AssertionError if false. Calls to this method will not be generated if -Xelide-below is greater than ASSERTION.
答案 4 :(得分:0)
需求,确保和不变性是按合同设计(CBD)开发过程中的概念。
require检查调用者使用该例程应满足的前提条件。
确保检查返回值的正确性(并仅验证所需的更改已发生,仅此而已)
不变性在所有关键时刻检查类的有效性。
CBD是一种用于构建正确/健壮软件的开发方法。有关CBD Google的更多详细信息,您应该点击Eiffel Software的链接。希望这会有所帮助。
答案 5 :(得分:0)
您可以在here中查看有关Scala语言的详细讨论。
我可以补充一点,区分require
和assert
的关键是理解这两个。这两个都是软件质量工具,但是来自不同范式的不同工具箱。概括而言,assert
是采用纠正方法的软件测试工具,而require
是采用预防方法的按合同设计工具。
require
和assert
都是控制状态有效性的手段。从历史上看,有两种截然不同的范例来处理无效状态。第一个是主流,统称为软件测试学科方法和工具。另一个称为按合同设计。这是两个无法比较的范式。
软件测试可确保代码具有足够的通用性,能够执行容易出错的操作,并且不会被滥用。 按合同设计控制代码具有这种功能。换句话说,软件测试是纠正性的,而按合同设计是预防性的。
assert
用于编写单元测试,即,如果某个方法通过所有由assert
表达式编写的测试,则该代码将被视为无错误。因此,assert
除了运营代码外,还是一个独立的机构。require
嵌入在代码中,并且部分代码可确保不会发生任何有害的事情。