有效的java建议我们不要捕获NullPointerException。总是对的吗?
几乎在所有情况下它都是正确的。
NullPointerException
通常是错误的结果;即您的应用程序遇到了null
在未预料到的情况下对象引用,然后尝试使用它。在这种情况下,由于您(程序员)没有预料到null
,几乎不可能知道它是否安全attempt恢复和/或了解可能需要什么“补救措施”。因此,最好的办法是让 NPE 传播到基础级别,然后将其视为一般错误。 (在“网络服务”应用程序中,返回“服务错误”响应并尝试继续可能是适当的。)
另一种情况是您(程序员)预计null
可能会被交付。在这种情况下,最好的策略是(几乎总是)显式测试null
before您尝试使用它,从而avoidingNPE ...以及处理它的需要。有两个原因:
请注意,我通过说“几乎总是”来限定上述内容。从理论上讲,有可能出现这样一种情况:显式测试null
让你的代码变得如此混乱,至少是值得的考虑到允许 NPE 发生。然而,仍然存在意外 NPE 的可能性……具体取决于代码。所以这种方法总是潜在地脆弱的。
(FWIW - 我从未遇到过这是一个好主意的真实案例......)
在许多捕获 NullPointerException 的情况下,捕获体仅调用 printStackTrace()。
那可能是糟糕的代码。什么都不做很少是从 NPE 中恢复的正确方法。
如果我没有捕获 NullPointerException 并调用 printStackTrace(),我如何检查发生异常的位置?
您让 NPE 传播到基础级别。在那里你捕获并打印(或记录)堆栈跟踪all未处理的异常,然后要么退出或尝试恢复......如果可行的话。
而且,如果我捕获 NullPointerException 并且捕获体为空,那么我们当时无法获取任何堆栈信息,不是吗?
永远、永远不要这样做!它被称为“挤压”,并且是危险的。 (特别是,正如我上面所解释的,NPE 可能是由于您/您的代码没有预料到的原因造成的。)
不,如果你这样做,你将无法获得堆栈跟踪。它消失了。
FOLLOWUP
I don't place much trust / faith on some general strategies for "avoiding NPEs"1. For instance stuff like this:
return (someObject != null) ? someObject.toString() : "";
总是让我怀疑程序员是没有思考问题。为何someObject
a null
首先?
NPE 是由以下原因引起的null
在你意想不到的地方。因此,NPE 通常是symptoms问题本身,而不是实际问题本身。在我看来,NPE 是不可避免的。相反,您应该使用 NPE 来查找并修复根本原因出乎意料的null
。像上面这样避免 NPE 的代码会妨碍该目标。
所以我更喜欢/推荐避免的策略null
值在意想不到的地方。
确保每个引用字段都初始化为非空值...除非null
is a 有意义的 value.
尽量避免null
作为一个有意义的值,特别是如果有替代方案的话。例如,一个空字符串、一个零长度数组、一个空集合、一个表示“未定义”的杰出实例或其他任何内容。或者,对于 Java 8 及更高版本,使用Optional
.
不要回来null
作为错误或特殊情况的指示。 (抛出异常或返回一个可区分的值。)
尽早检查是否有意外情况null
值(例如null
参数),并抛出 NPE宜早不宜迟.
在少数几个地方null
参数或结果是合法的,请确保您的 javadocs 清楚明确地记录这一点。如果没有文档,那么含义应该是null
是不允许的,并且不会被退回。
无论您在何处遇到 NPE,请确保找到并修复该问题real问题的根源......不仅仅是抛出异常的具体语句。
1 - There is value in knowing about places in the standard Java APIs where null
is used (or abused) as a return value. For instance, Class.getResourceAsStream(...)
or HttpRequest.getParam(...)
. Those "advice for avoiding NPE" documents are useful in as much that they point out these traps.