Java 断言一个好的做法与否?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2440984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Assert a good practice or not?
提问by ken
Is it a good practice to use Assert for function parameters to enforce their validity. I was going through the source code of Spring Framework and I noticed that they use Assert.notNull
a lot. Here's an example
对函数参数使用 Assert 以强制其有效性是否是一种好习惯。我正在浏览 Spring Framework 的源代码,我注意到它们使用Assert.notNull
了很多。这是一个例子
public static ParsedSql parseSqlStatement(String sql) {
Assert.notNull(sql, "SQL must not be null");
}
Here's Another one:
这是另一个:
public NamedParameterJdbcTemplate(DataSource dataSource) {
Assert.notNull(dataSource,
"The [dataSource] argument cannot be null.");
this.classicJdbcTemplate = new JdbcTemplate(dataSource);
}
public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
Assert.notNull(classicJdbcTemplate,
"JdbcTemplate must not be null");
this.classicJdbcTemplate = classicJdbcTemplate;
}
FYI, The Assert.notNull
(not the assert
statement) is defined in a util class as follows:
仅供参考,Assert.notNull
(不是assert
语句)在 util 类中定义如下:
public abstract class Assert {
public static void notNull(Object object, String message) {
if (object == null) {
throw new IllegalArgumentException (message);
}
}
}
采纳答案by polygenelubricants
In principle, assertionsare not that different from many other run-time checkings.
原则上,断言与许多其他运行时检查没有什么不同。
For example, Java bound-checks all array accesses at run-time. Does this make things a bit slower? Yes. Is it beneficial? Absolutely! As soon as out-of-bound violation occurs, an exception is thrown and the programmer is alerted to any possible bug! The behavior in other systems where array accesses are not bound-checked are A LOT MORE UNPREDICTABLE! (often with disastrous consequences!).
例如,Java 在运行时对所有数组访问进行边界检查。这会让事情变慢吗?是的。有好处吗?绝对地!一旦发生越界违规,就会抛出异常并提醒程序员注意任何可能的错误!在其他系统中,数组访问未进行边界检查的行为更加不可预测!(通常会带来灾难性的后果!)。
Assertions, whether you use library or language support, is similar in spirit. There are performance costs, but it's absolutely worth it. In fact, assertions are even more valuable because it's explicit, and it communicates higher-level concepts.
断言,无论您使用库还是语言支持,在精神上都是相似的。有性能成本,但绝对值得。事实上,断言甚至更有价值,因为它是明确的,并且它传达了更高级别的概念。
Used properly, the performance cost can be minimized and the value, both for the client (who will catch contract violations sooner rather than later) and the developers (because the contract is self-enforcingand self-documenting), is maximized.
如果使用得当,性能成本可以最小化,并且对于客户(他们将很快发现违反合同的行为)和开发人员(因为合同是自我执行和自我记录的)的价值最大化。
Another way to look at it is to think of assertions as "active comments". There's no arguing that comments are useful, but they're PASSIVE; computationally they do nothing. By formulating some concepts as assertions instead of comments, they become ACTIVE. They actually must hold at run time; violations will be caught.
另一种看待它的方式是将断言视为“主动评论”。毫无疑问,评论是有用的,但它们是被动的;在计算上他们什么都不做。通过将一些概念表述为断言而不是评论,它们变得活跃。它们实际上必须在运行时保持;违规将被抓获。
See also: the benefits of programming with assertions
另请参阅:使用断言编程的好处
回答by cletus
Yes it's a good idea. You're enforcing the contracting of the interface or class. If there is a contract violation you want to detect it as soon as possible. The longer you wait the more unpredictable the results can be and the harder it can be to diagnose.
是的,这是个好主意。您正在强制执行接口或类的合同。如果存在违反合同的情况,您希望尽快发现。您等待的时间越长,结果就越不可预测,诊断起来就越困难。
When you explicitly check like this you should also provide an information message that when viewed in a log file can give useful context to help find the root cause or even just to realize you've made a wrong assumption about what the contract is.
当您像这样明确检查时,您还应该提供一条信息消息,当在日志文件中查看时,可以提供有用的上下文来帮助找到根本原因,甚至只是意识到您对合同的内容做出了错误的假设。
回答by Stephen C
Yes it is good practice.
是的,这是很好的做法。
In the Spring case, it is particularly important because the checks are validating property settings, etc that are typically coming from XML wiring files. In other words, they are validating the webapp's configuration. And if you ever do any serious Spring-based development, those validation checks will save you hours of debugging when you make a silly configuration mistake.
在 Spring 的情况下,这尤其重要,因为检查正在验证通常来自 XML 连接文件的属性设置等。换句话说,他们正在验证 webapp 的配置。如果您曾经进行过任何严肃的基于 Spring 的开发,那么当您犯下愚蠢的配置错误时,这些验证检查将为您节省数小时的调试时间。
But note that there is a BIG difference between a library class called Assert
and the Java assert
keyword which is used to define a Java assertion. The latter form of assertions can be turned off at application launch time, and should NOT be used for argument validation checks that you always want to happen. Clearly, the Spring designers think it would be a really bad idea to turn off webapp configuration sanity checks ... and I agree.
但请注意,称为库类Assert
和assert
用于定义 Java 断言的 Java关键字之间存在很大差异。后一种形式的断言可以在应用程序启动时关闭,并且不应用于您总是希望发生的参数验证检查。显然,Spring 设计者认为关闭 webapp 配置健全性检查是一个非常糟糕的主意……我同意。
UPDATE
更新
In Java 7 (and later) the java.util.Objects
class provides a requireNonNull
convenience method to test if an argument is null
and raise an exception. You use it like this:
在 Java 7(及更高版本)中,java.util.Objects
该类提供了一种requireNonNull
方便的方法来测试参数是否存在null
并引发异常。你像这样使用它:
SomeType t = ...
SomeType tChecked = Objects.requireNonNull(t);
or
或者
SomeType tChecked = Objects.requireNonNull(t, "t should be non-null");
However, note that this method raises NullPointerException
rather than IllegalArgumentException
.
但是,请注意,此方法引发NullPointerException
而不是IllegalArgumentException
。
回答by Michael Myers
Those asserts are library-supplied and are not the same as the built-in assert
keyword.
这些断言是库提供的,与内置assert
关键字不同。
There's a difference here: assert
s do not run by default (they must be enabled with the -ea
parameter), while the assertions provided by the Assert
class cannot be disabled.
这里有一个区别:assert
默认情况下 s 不运行(必须使用-ea
参数启用它们),而Assert
不能禁用类提供的断言。
In my opinion (for what it's worth), this is as good a method as any for validating parameters. If you had used built-in assertions as the question title implies, I would have argued against it on the basis that necessary checks should not be removable. But this way is just shorthand for:
在我看来(就其价值而言),这是一种与验证参数的任何方法一样好的方法。如果您像问题标题所暗示的那样使用内置断言,我会反对它,因为必要的检查不应该是可移动的。但这种方式只是简写:
public static ParsedSql parseSqlStatement(String sql) {
if (sql == null)
throw new IllegalArgumentException("SQL must not be null");
...
}
... which is always good practice to do in public methods.
...这在公共方法中总是很好的做法。
The built-in style of asserts is more useful for situations where a condition should always be true, or for private methods. The language guide introducing assertionshas some good guidelines which are basically what I've just described.
断言的内置样式对于条件应该始终为真的情况或私有方法更有用。介绍断言的语言指南有一些很好的指南,这些指南基本上就是我刚刚描述的内容。
回答by kiwicptn
Based on Sun's guideon assertions, you should notuse assertions for argument checking in public methods.
基于Sun的指南上断言,您应该不使用断言的争论在公共方法检查。
Argument checking is typically part of the published specifications (or contract) of a method, and these specifications must be obeyed whether assertions are enabled or disabled.
参数检查通常是方法的已发布规范(或合同)的一部分,无论断言是启用还是禁用,都必须遵守这些规范。
回答by Dariusz Cieslak
I'm keeping my assertions in released binariesbut with modified behavior: abort is not called but stacktrace is collected.
我将我的断言保留在已发布的二进制文件中,但具有修改的行为:不调用 abort 但收集堆栈跟踪。
More details here: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/
更多细节在这里:http: //blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/
回答by nclark
In very large and poorly designed/maintained systems, if you're looking to improve predictability in methods that are, say, 6000 lines long and nobody in the company understands them anymore, it can be valuable to use the assert keyword to cause development environments to blow up, revealing bugs. But were you to implement those assertions in production, you might shortcircuit a patch that, though horribly conceived, fixed a problem. You want to fix that bad patch by discovering it in the dev environment, not production. So you would turn asserts on at development time, and turn them off in production.
在非常大且设计/维护不佳的系统中,如果您希望提高 6000 行长的方法的可预测性,并且公司中没有人再了解它们,那么使用 assert 关键字来创建开发环境可能很有价值炸毁,揭示错误。但是如果你在生产中实现这些断言,你可能会短路一个补丁,虽然构思很糟糕,但解决了一个问题。您希望通过在开发环境而不是生产环境中发现该错误补丁来修复它。所以你会在开发时打开断言,并在生产中关闭它们。
Another valid use of the assert keyword at development time is to insert validity checks into algorithms that must execute in sub-millisecond times and are well enough insulated from unpredictable or untested callers. You may not be able to afford to preserve the validity check in production in such a case, though it's still very useful in development. On the other hand, if the source of the parameters you're validating is unpredictable or could become so (if it's determined partly by user input, for example), you can probably never afford to skip the check, even in production, and should take the performance hit as a cost of doing business. (In this last case, you probably wouldn't want to use an assert.) But you should opt for asserts to eliminate a production-time validity check onlyafter profiling tells you you simply can't afford the overhead.
在开发时,assert 关键字的另一个有效用途是将有效性检查插入到必须在亚毫秒时间内执行并且与不可预测或未经测试的调用者充分隔离的算法中。在这种情况下,您可能无法在生产中保留有效性检查,尽管它在开发中仍然非常有用。另一方面,如果您验证的参数的来源是不可预测的或可能变成这样(例如,如果它部分由用户输入决定),您可能永远无法跳过检查,即使在生产中,并且应该将性能损失视为开展业务的成本。(在最后这种情况下,你可能不希望使用一个断言。)但你应该选择断言,以消除生产时间有效性检查只分析后告诉您,您根本负担不起开销。