为什么断言不能用于公共方法中的参数检查?

ano*_*428 8 java methods assert arguments

好吧,我在java的有限经验中从未真正使用过断言,并且想知道为什么我在许多网站上阅读过很多关于断言的书籍,同样的警告断言语句不应该用于参数检查公共方法?我想知道这是否与assert语句相对于java中其他语句的执行顺序有关.

das*_*ght 5

非正式地,参数检查和断言有不同的目的:

  • 参数检查是为了检测调用你的方法的人做错事的情况,而
  • 断言用于检测做错某事时的情况。

本质上,当你断言一个条件时

assert val < total;
Run Code Online (Sandbox Code Playgroud)

该检查向代码的读者传达了以下简单的英语思想:“我检查了我的代码,根据我的推理,我确信将val永远小于total”。

val另一方面,当你检查一个参数时,

if (val >= total) throw new InvalidArgumentException("val");
Run Code Online (Sandbox Code Playgroud)

您的代码表示“调用者忘记确保小于valtotal

这是两种不同的想法,因此很自然地在代码中采用两种不同的方式来表达它们。


Hot*_*cks 5

断言的目的是检查你的程序逻辑——断言失败是“停止一切——有一个错误!” 指示。特别是,断言失败表明“这里有一个错误”,但“这里”是代码内部的某个地方,并且失败的原因只能通过检查您的代码来真正确定(您的 API 的用户不能也不应该这样做)预计不会这样做)。

当您通过 API 获得不良数据时,您需要表示“嘿!您给了我不良数据!” IllegalArgumentException 及其同类是表明这一点的方法。

(但请注意,在代码中对参数使用断言检查并没有什么问题——在这种情况下,您不支持将由团队外部的人员使用的真正“公共”API。)

但这确实提出了另一点:在合理/可能的范围内,您应该“捕获”由于您自己的错误而可能发生的 IllegalArgumentException 等内部异常,并将它们转换为 FatalError 异常或类似的异常,因此 API 的用户当您的代码中存在错误时,不会导致他去寻找错误的参数。

(另请注意 Java 关键字和“公共接口”之间的区别public,这意味着某些接口作为“正式”API 可供编程团队之外的个人使用。我们是后一种情况。我很担心这里。)