什么时候可以捕获 NullPointerException?

2023-11-21

有效的java建议我们不应该catch NullPointerException。 总是对的吗?

在很多抓捕的情况下NullPointerException, 仅捕获正文调用printStackTrace().

如果我没抓住NullPointerException并打电话printStackTrace(),我如何检查该位置exception发生了?

而且如果我抓住NullPointerExceptioncatchbody 为空,此时我们无法获取任何堆栈信息,可以吗?

UPDATE

我分析了谷歌android源代码AOSP4.2.2_r1.2中捕获RuntimeException的统计数据。

有 249 个 RuntimeException 捕获,以下是 catch-body 的统计信息。

42%: throw it again as other Exceptions (RuntimeException: 33%, others: 8%)

32%: just return null or 0/false/true or other default values

14%: just call log or printstacktrace

5%: just comment like "// Fall through.", "// ignore, not a valid type.", "// system process dead", "// do nothing"

2%: empty body

3%: display error messages or send fail codes (ex. network service discovery failed: replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); )


3%: intialize or reset related variables.

在大多数情况下,dalvik 和外部通过抛出其他异常来处理 NPE。

但框架通常通过返回 null 或其他值来处理。

  1. 您认为在 catch-body 中抛出其他异常是不是不好或很好的处理?

  2. 如果 NPE 发生在更高级别(例如应用程序),并且开发人员确认异常并不重要,因为应用程序是完全独立的,我可以接受我们的开发人员通过捕获来忽略 NPE 吗?

还有一件事情,

我是否可以得出结论,google android框架源代码可能在以下方面有些不稳定RuntimeException?


有效的java建议我们不要捕获NullPointerException。总是对的吗?

几乎在所有情况下它都是正确的。

NullPointerException通常是错误的结果;即您的应用程序遇到了null在未预料到的情况下对象引用,然后尝试使用它。在这种情况下,由于您(程序员)没有预料到null,几乎不可能知道它是否安全attempt恢复和/或了解可能需要什么“补救措施”。因此,最好的办法是让 NPE 传播到基础级别,然后将其视为一般错误。 (在“网络服务”应用程序中,返回“服务错误”响应并尝试继续可能是适当的。)

另一种情况是您(程序员)预计null可能会被交付。在这种情况下,最好的策略是(几乎总是)显式测试null before您尝试使用它,从而avoidingNPE ...以及处理它的需要。有两个原因:

  • 异常处理通常是昂贵的。确实可以许多数量级比测试更昂贵null.

  • 如果您允许预期的 NPE 发生然后捕获它,您也可能会捕获其他 NPE意外NPE……并错误地处理它们。


请注意,我通过说“几乎总是”来限定上述内容。从理论上讲,有可能出现这样一种情况:显式测试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.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么时候可以捕获 NullPointerException? 的相关文章

随机推荐

  • linq 异常:只能从 LINQ to Entities 调用此函数

    我正在尝试获取保存在缓存中的数据 但它在 select new FilterSsrsLog 行上引发异常 例外 此函数只能从 LINQ to Entities 调用 List
  • 自动导入包的顺序和歧义

    JLS 第 7 章 软件包 一个包由许多编译单元组成 第 7 3 节 一个编译单元自动有权访问其包中声明的所有类型并且自动导入预定义包 java lang 中声明的所有公共类型 让我们假设以下代码 package com example p
  • jQuery 日期时间选择器 MVC3

    我的模型中有这个字段 DataType DataType DateTime Required ErrorMessage Expire is required public DateTime Expire get set 在我看来 Html
  • 在 JavaScript 中定义全局对象的独立于实现的版本

    我正在尝试定义globalJavaScript 中的对象在一行中如下所示 var global this global this 上述声明是在全局范围内的 因此在浏览器中this指针是一个别名window目的 假设它是在当前网页上下文中执行
  • 将 key=value 对转换回 Python 字典

    有一个日志文件 其中的文本以空格分隔key value对 每行最初都是从 Python 字典中的数据序列化的 类似于 join f k v r for k v in d items 键始终只是字符串 这些值可以是任何值ast literal
  • Keras 自定义指标迭代

    我对 Keras 还很陌生 我正在尝试定义自己的指标 它计算一致性指数 这是回归问题的度量 def cindex score y true y pred sum 0 pair 0 for i in range 1 len y true fo
  • 如何在 Angular/ionic 网站中实施 AMP?

    最近我听说了 Accelerated Mobile Pages 项目 并阅读了一些有关它的信息 我想知道如何为基于 Ionic 和 Angular 构建的现有网站实现它 基本上没有几乎可能的解决方案可以做到这一点 如果你检查文档here 让
  • Android Studio 无法启动

    安装Android Studio后 我启动了它 但它没有开始 我打开任务管理器看到多了两个执行顺序 Cmd exe and conhost exe 我的系统版本是Windows 7 Ultimate 64bit 有什么想法如何解决这个问题吗
  • 在 Web API / APIController 中控制序列化

    在 ASP NET Web API 中哪里可以指定自定义序列化 反序列化 我们应用程序的吞吐量需要消息的快速序列化 反序列化 因此我们需要严格控制这部分代码以使用我们的自制程序或 OSS 我检查了各种来源 例如this这解释了如何创建自定义
  • 当注释有参数时,CDI 拦截器不起作用

    我正在尝试实现一个 Restricted注释 以用户只有在登录并具有特定角色时才能访问它们的方式保护控制器方法 我在 Tomcat 7 上使用 JSF 和 CDI 所以没有 EJB 只要注释接口不指定任何参数 拦截器就会被调用 一旦我添加一
  • JAXB 文档注释

    我有以下带有 JAXB XMLRootElement 注释的 java 类 XmlRootElement name ClientData public class ClientData The first address field of
  • 由于内存问题导致realloc失败时如何处理?

    问题说明了一切 但这是一个例子 typedef struct mutable t int count max void data mutable t void pushMutable mutable t m void object if m
  • 将字符串中的一些小写字母更改为大写

    index 0 2 5 s I am like stackoverflow python for i in index s s i upper print s IndexError string index out of range 我知道
  • 使用 getopt 向命令行选项提供两个参数[重复]

    这个问题在这里已经有答案了 使用时是否有其他方法将两个参数作为单个字符串传递给选项getopt 通常我会执行以下操作 command o key value command arguments 然后我必须明确地分割参数字符串 while o
  • 如何获取ng-bootstrap中Dropdown的值?

    我正在使用 ng bootstrap 我想在选择时获取下拉列表的值 div class col text right div class d inline block div div
  • 如何从部分视图获取父视图

    我有一个部分视图作为 Layout cshtml 的一部分 以便它可以在多个页面上呈现 将部分视图视为显示在网站每个页面上的菜单 当单击部分视图菜单中的这些链接之一时 我只能在称为部分视图的操作方法中访问 查看 如它的名称等 但我真正需要的
  • 无法更改视图的默认布局边距

    从ios 8 0开始 视图有额外的layoutMargins默认情况下 每边都有 8 分值 当我尝试更改边距时viewDidLoad它似乎对孩子的看法没有影响 override func viewDidLoad super viewDidL
  • Python lambda函数打印 at 0x7fcbbc740668>而不是值

    我是 python 的初学者 我正在研究 lambda 函数 我正在编写一个程序 使用 lambda 函数来打印输入字符的 ascii 值 1 的字符 我的代码是 usr bin python import sys try word sys
  • NoClassDefFoundError:org/slf4j/Logger

    我将 Log4J2 添加到我的应用程序中 我将所有 Log4J2 jar 文件复制到 LIB 目录并创建 Log4J2 xml 文件来支持它 我的代码已更新以导入必要的日志管理器和记录器 API 然后 我添加了静态最终记录器方法 并在代码中
  • 什么时候可以捕获 NullPointerException?

    有效的java建议我们不应该catch NullPointerException 总是对的吗 在很多抓捕的情况下NullPointerException 仅捕获正文调用printStackTrace 如果我没抓住NullPointerExc