Java 为什么可以';我们不能对公共方法使用断言吗?

Java 为什么可以';我们不能对公共方法使用断言吗?,java,assert,public-method,Java,Assert,Public Method,为什么我们不能对公共方法使用断言 我在什么地方读过 “断言在公共场合是不合适的 方法,因为该方法保证 它将始终执行 参数检查。必须使用公共方法 检查其参数是否正确 断言已启用 断言构造不抛出 指定类型的异常。它是 只能抛出一个断言错误 那么,它也适用于私有方法吗? 我没有清楚地理解上面的陈述总的来说,这似乎是合理的。尽管在某些情况下这可能是有用的 考虑一下,我们可能希望对已知存在的元素执行数据库更新操作。然后,查看例程是否成功可能很有用,例如: public void update(Object

为什么我们不能对公共方法使用断言

我在什么地方读过

“断言在公共场合是不合适的 方法,因为该方法保证 它将始终执行 参数检查。必须使用公共方法 检查其参数是否正确 断言已启用 断言构造不抛出 指定类型的异常。它是 只能抛出一个断言错误

那么,它也适用于私有方法吗?

我没有清楚地理解上面的陈述

总的来说,这似乎是合理的。尽管在某些情况下这可能是有用的

考虑一下,我们可能希望对已知存在的元素执行
数据库更新
操作。然后,查看例程是否成功可能很有用,例如:

public void update(Object o) {
   int nUpdatedObjects = dao.update(o);
   assert(nUpdatedObjects == 1)
}

在这种情况下,它使用

断言用于调试;公共方法通常不应该通过调试断言来验证,而是通过执行适当的参数检查和抛出适当的异常来验证。如果要验证内部对象状态,可以使用它,但不要验证参数。

重要的区别在于您是否认为错误的值是

a) 应该在代码中修复的编程错误

b) 无法在代码中防止的输入错误,需要在运行时处理

对于第一种情况,您应该使用断言,因为程序代码需要修复。如果是后一种情况,则应使用适当的运行时或检查异常


IMHO断言用于检测编程错误,而不是用户/外部输入。当您将有一个不被外部输入调用的公共方法时,作者可能混淆了公共方法作为外部输入

我将使用断言检查参数以检测编程错误。我认为这通常是它们的最佳用途。通过比较,私有方法只能由同一类中的代码调用,您应该期望它们是良好的单元测试,并且具有有限的可能访问/使用


我发现,由于不同的人做出不同的假设(断言是记录和检查假设的好方法),通过公共接口,您更可能出现编程错误如果没有编写完整的内部代码库,内部检查并不像您期望的那样有用。

这个想法是您不知道谁会使用您的公共方法。因此,您必须通过正常检查来防止不当使用

另一方面,私有方法应该仅由当前团队中的开发人员使用,因此检查不是强制性的(但仍然建议IMHO)


所以,对于检查私有方法上的参数有效性,断言应该足够了

我相信,你引用的这句话是胡说八道

可以肯定的是,assert不是用于验证参数的

但在每一个非平凡的程序中都有(或应该有)许多不变量,而这正是断言派上用场的地方。如果可以在断言中表示不变量,请这样做,无论该方法是否公开

然后,将发生以下情况之一:

a) 一切都很好。

b) 在运行时,程序会因未实现的断言而失败。如果断言是正确的,则不变量被违反,您有机会找出原因并修复错误(或重新思考您的设计)。

断言不应用于检查公共方法中的参数,原因如下:

  • 断言可以被禁用,参数检查永远不应该被禁用,因为它们是方法与其调用方的契约的一部分
  • 断言失败不会为无效参数引发适当的异常
例如:

    /**
     * @throws ArithmeticException if divisor is zero
     */ 
    public void int divide(int divisor) {
        if (divisor == 0) {
            throw new ArithmeticException("Cannot divide by zero");
        }
        ...
    }

如果您在这里使用断言,它可能会被关闭,它会抛出一个
断言FailedException
,这是没有帮助和没有信息的。

我给出了一个不完全正确的响应。当然,您可以在公共方法(或任何您喜欢的地方)中使用assert

重点在于你该做什么或不该做什么。我自己完全理解其他人对何时应该或不应该使用断言的反应

但我必须承认,我从未使用断言,而且我很少在代码中看到断言。我只工作了几年,但在我工作过的4家完全不同的公司中,代码中没有断言。无论是用于预订航班的1000多万行代码web应用程序、航天器控制中心、管理大型超市的软件还是bug追踪器。他们都没有使用资产。所有公司都有不同的需求和方法。未使用任何资产

对我来说,原因很简单。这里的人说断言是用于调试的。那很好。您可以停用它们以提高速度。那也很好。。。一开始程序越复杂,调试时间越长。有些bug,即使是100%的代码覆盖率,即使是广泛的集成和验证测试,也只能在生产中找到。只是因为你的用户最终使用你的应用程序比你多。他们不会像你一样使用它

这很有趣,因为在生产日志中,我们不断看到代码中的堆栈跟踪,如下所示:

catch (MyException e) {
  logger.war("This should never happen",e);
}
这意味着你永远不知道生产中会发生什么

如果你有机会做一个检查,就去做。当然,这里的日志注释比有用的更有趣,最好让异常弹出

在所有情况下,不要将其作为将在生产中禁用的断言。因为它将是无用的。使其成为引发异常的普通代码。如果合适,请确保已记录。确保