【发布时间】:2009-09-18 12:44:02
【问题描述】:
我来自 .NET 背景,现在涉足 Java。
目前,我在设计一个针对错误输入的防御性 API 时遇到了很大的问题。假设我有以下代码(足够接近):
public void setTokens(Node node, int newTokens) {
tokens.put(node, newTokens);
}
但是,此代码可能会因两个原因而失败:
- 用户传递了一个
null节点。 - 用户传递了一个无效节点,即图中未包含的节点。
在 .NET 中,我会分别抛出 ArgumentNullException(而不是 NullReferenceException!)或 ArgumentException,将违规参数的名称 (node) 作为 string 参数传递。
Java 似乎没有等效的异常。我意识到我可以更具体,只抛出最接近描述情况的任何异常,甚至为特定情况编写我自己的异常类。
这是最佳做法吗?或者.NET中是否有类似于ArgumentException的通用类?
在这种情况下检查null 是否有意义?无论如何,代码都会失败,异常的堆栈跟踪将包含上述方法调用。检查null 似乎是多余和过度的。当然,堆栈跟踪将稍微更干净(因为它的目标是上述方法,而不是 JRE 的 HashMap 实现中的内部检查)。但这必须抵消额外的 if 语句的成本,此外,无论如何永远不会发生 - 毕竟,将 null 传递给上述方法不是预期的情况,这是一个相当愚蠢的错误。期待它是彻头彻尾的偏执 - 即使我不检查它也会失败并出现同样的异常。
[正如 cmets 中所指出的,HashMap.put 实际上允许 null 键值。所以在这里检查null 不一定是多余的。]
【问题讨论】:
-
调用
setTokens(null,0)只会在您使用Hashtable或ConcurrentHashMap时抛出NullPointerException,因为它们不允许使用null键。另一方面,HashMap很高兴拥有空键。 -
@pjp:感谢您的更正——我原以为会失败,因为
HashMap需要创建其参数的哈希值。我猜还有一个明确检查的原因。
标签: java exception defensive-programming