论断言和例外; Java的

时间:2011-02-01 14:24:59

标签: java exception assert

在这种特定场景中,断言是否比例外更合适?

据我了解,当程序FUBAR达到无法恢复并退出的程度时,应使用断言。

我还被告知要为了清晰度和错误消息处理而抛出异常。

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

   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);
    }

4 个答案:

答案 0 :(得分:4)

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

当然,断言只会抛出异常。如果您绝对想立即 ,那么您需要使用Runtime.halt之类的内容。

所以我喜欢这里的异常,虽然我给出一个空参数时通常使用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);
}

答案 1 :(得分:1)

一般规则(从here复制)

断言应该保护(不总是明显的)错误 开发者,例如尽管它是NULL,但使用指针。

异常是一种处理可能合法发生的错误的方法 运行时,例如尝试连接到某个服务器的失败(可能 因各种原因没有回应。)

使用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);
}

答案 2 :(得分:0)

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

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

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

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

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

答案 3 :(得分:0)

Java technote Programming With Assertions包含有关usage的明确界线:

  

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

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