论断言和例外; Java的

在这个特定的场景中,断言比exception更合适吗?

据我所知,当程序FUBAR达到无法恢复并退出的程度时,应使用assert。

我还被告知要始终抛出exception以便清晰和错误消息处理。

每次使用时间之间是否存在细微差别? 有没有一个例子,必须无条件地使用断言代替例外?

public void subscribe(DataConsumer c) throws IllegalArgumentException { if (c == null) { // Almost certainly FUBAR throw new IllegalArgumentException("Can't subscribe null as a DataConsumer. Object not initialized"); } if (dataConsumerList == null) { // Definetely FUBAR throw new IllegalArgumentException("Nothing to subscribe to. DataConsumerList is null"); } dataConsumerList.add(c); } 

就个人而言,我并不热衷于使用断言来解决这类问题,因为它们可以被关闭。 有些地方在运行测试时使用断言,但为了速度而禁用它们进行生产。 对我来说,这就像正常进行驾驶考试一样,但是当你上高速公路时,就要取下安全带。

当然,断言只会抛出exception。 如果你现在绝对想要关闭JVM,你需要使用像Runtime.halt这样的东西。

所以我在这里是exception的粉丝,虽然我在给定null参数时通常使用NullPointerException ,并且如果dataConsumerList是你的状态的一部分,那么我个人会使用IllegalStateException来区分这种情况。 (遗憾的是,Java没有与.NET相同的ArgmentNullException ,给出了常见的检查。)

Guava有一个有用的Preconditions类,可以让你更简洁地写出:

 public void subscribe(DataConsumer c) throws IllegalArgumentException { Preconditions.checkNotNull(c, "Can't subscribe null as a DataConsumer. Object not initialized"); Preconditions.checkState(dataConsumerList != null, "Nothing to subscribe to. DataConsumerList is null"); dataConsumerList.add(c); } 

一般规则(从这里复制)

断言应该保护开发人员的错误(并不总是显而易见的),例如使用指针尽管它是NULL。

exception是一种处理可能在运行时合法发生的错误的方法,例如尝试连接到某个服务器的失败(可能由于各种原因而无法响应)。

使用google-guava Preconditions.checkNotNull()类编写上述代码有一种更好的方法。

 public void subscribe(DataConsumer c) throws IllegalArgumentException { checkNotNull(c, "Can't subscribe null as a DataConsumer. Object not initialized"); checkNotNull(dataConsumerList , "Nothing to subscribe to. DataConsumerList is null"); dataConsumerList.add(c); } 

如果您可以用英语术语来表达,请使用assert作为“gotta”(Got to,Must)和“otta”的例外(应该是,应该)。

将断言用于显示停止,关键条件必须为true才能继续执行。 示例可能是分区正确发生(想想英特尔芯片浮点错误)或者在正确打开它之后数据库连接不为空。 如果发生了这些,则程序执行不应继续。

使用throw来解决您的方法可能遇到的可预见错误。 抛出是合同的一部分,向您和其他程序员声明可能遇到某些类型的错误(并且这不是您的责任)。

在您的示例中,我的猜测是在正常情况下永远不会发生null使用者或空列表。 如果我的猜测是正确的,那么你会想在这里使用一个断言,声明subscribe()将处理它。

如果我的猜测是错误的并且发生了一个空的消费者,比如50次中的1次,则抛出会更好,你会声明subscribe()与调用方法形成一个契约,从而调用方法处理错误。

Java技术说明使用断言编程包含有关用法的显式行:

不要在公共方法中使用断言进行参数检查。

这应该是你的问题的一个非常确定的答案。