【问题标题】:If catching null pointer exception is not a good practice, is catching exception a good one?如果捕获空指针异常不是一个好习惯,那么捕获异常是一个好习惯吗?
【发布时间】:2011-01-17 18:13:06
【问题描述】:

我听说捕捉NullPointerException 是一种不好的做法,我认为这是明智的。让NullPointerException 传播到顶部将允许检测出问题。但是很多时候我看到我的很多朋友直接捕捉到Exception,这样他们就不必为上面代码中可能出现的所有不同类型的异常而烦恼。这是一个好习惯吗?最好不处理的其他类型的异常是什么?此外,在我们确定异常来源的特定代码上处理NullPointerException 对我来说也是有意义的。那么什么时候处理异常,什么时候不处理呢?最好不要处理的可能的异常列表是什么?

【问题讨论】:

  • "I have heard that catching NullPointerException is a bad practice, and i think it is sensibly so. Letting the NullPointerException to propagate to the top would allow the detection of a something going wrong" 对我来说没有多大意义。你不是把“抓”和“吞”混为一谈吗?
  • 捕获NullPointerException 并对其进行处理并没有错。这适用于任何例外。总的想法是捕获可以处理的异常,而不是捕获(传递)那些无法处理的异常。所以我不得不不同意你所听到的。

标签: java exception exception-handling nullpointerexception


【解决方案1】:

Pokemon 异常处理很糟糕。特别是,如果它是一个空块,而您只是在吞食它们。您有特定类型的异常,因为它们实际上意味着特定上下文中的特定事物(本质上它们是在告诉您出了什么问题)。因此,通过捕获Exception,您是在说您不在乎这些异常是什么,也不在乎发生了什么。这可能不是你想要的。

一般来说,捕捉异常时遵循以下规则:

  • 在这个级别处理异常有意义吗?如果是,则处理它。如果没有,则传播。
  • 结合第一条规则,“处理”还可以表示捕捉、包装和重新投掷。这是一种防止抽象泄漏的方法,因此您的方法的调用者不必了解底层实现。
  • 空的 catch 块并不意味着您已经处理了异常。这就是所谓的“吞咽”;至少,您要记录异常。有时发生异常实际上是代码逻辑流程的一部分,因此您可能想做一些特别的事情(但请原谅双关语,例外而不是规则。最好检查导致异常的情况而不是将它们合并到代码的逻辑流中)。

您可以轻松地检查代码中的空值,因此无需显式捕获空指针异常。让NullPointerException 发生是没有意义的(这是不好的做法)。即使您有一些代码会引发NullPointerException,并且这是您无法控制且无法修复的代码,您也应该确定导致NullPointerException 的输入参数并专门对其进行测试。

另一个您不应该捕获的异常是IllegalArgumentException。这个异常意味着你传入了一个没有意义的参数。您应该明确地测试您的输入参数,而不是捕获此异常,以确保它们是正常的并且它们不会导致IllegalArgumentException

【讨论】:

  • 什么是“口袋妖怪异常处理”?
  • catch(Exception ex){ 当你想把它们全部捕获时。
  • “口袋妖怪异常处理”:必须抓住所有的人:D
【解决方案2】:

捕获NullPointerException 被认为是一种不好的做法的“原因”并不是因为您应该在出现问题时让它冒泡!仅根据其类型说任何异常都“最好不处理”似乎是个坏主意。

NPE 被认为是编程错误的结果。一个严格正确的程序永远不应该生成一个。看到它被捕获的原因很糟糕,这通常意味着代码抛出了一个,程序员决定只是捕获它并掩盖它,而不是修复导致它的损坏代码!

例如,如果您出于业务原因与内部存在错误并偶尔抛出空指针的 API 耦合,那么捕获它是完全合法的,对此采取一些措施/用更好的消息通知用户.仅仅因为有人说“Catching Null Pointer Exception is bad”就让“null”点击 UI 是没有意义的!

捕获java.lang.Exception 在特定情况下可能是合法的,但通常“我很懒”不是其中之一。 :) 例如,如果您正在实现一个 API,并且希望绝对确保不会出现不在规范中的异常,您可能会捕获 Exception 并将其包装在您定义的某些应用程序异常中。

【讨论】:

    【解决方案3】:

    如果您可以通过这样做增加一些价值,您应该只捕获异常。否则你应该让它传递给调用者。

    NullPointerException 通常是代码中的错误的结果。如何在 catch 块中明智地解决此问题?

    不关心异常不是一个好习惯。

    【讨论】:

      【解决方案4】:

      一般而言,您应该捕获异常的唯一情况是您是否可以以某种有意义的方式处理它。如果你不能,你应该让它冒泡到顶部并终止该过程。例如,您能否以某种有意义的方式从 NullPointerException 或 I/O 错误中恢复?我认为不会。

      我的异常处理规则:

      • 一般来说,不要捕获异常,除非您能以某种有意义的方式处理它们。
      • 在进程/机器边界捕获异常,将捕获的异常与任何可用的上下文一起记录下来,然后重新抛出它。如果异常是自定义异常,您可以将其包装在调用进程已知/有用的类型的异常中并抛出该异常。
      • 您还可以在低级别捕获异常,在此您拥有最多的运行时上下文可用,记录异常和相关上下文,然后重新抛出异常。
      • 重新抛出时,使用throw ; 而不是throw caughtException ;。使用前一种语法会保留原始堆栈跟踪;使用后一种语法会创建一个新的堆栈跟踪,以 throw caughtException ; 开头——您会丢失所有上下文并调用堆栈,直到捕获到异常为止。
      • 如果您愿意,您可以在高级别捕获异常并优雅地终止进程,记录异常信息以帮助调试和纠正潜在问题。

      不要将异常用作流控制机制(如果可能)。例外在本质上应该是例外。相反,对于您正在调用的任何方法,先发制人地强制执行调用方的合同结束(前提条件)。

      请参阅 Bertrand Meyers 的书,Object Oriented Software Construction, 2nd ed. 了解更多信息。

      【讨论】:

      • 回复“重新抛出时”:在Java中不能“抛出;”,必须“抛出捕获异常;”并且您在执行此操作时不会丢失堆栈跟踪。
      【解决方案5】:

      关于捕获异常的主要规则是您必须知道为什么要这样做。当程序员想要进行通用错误处理并且他并不真正关心到底发生了什么时,会捕获异常类,主要的事情就是出了点问题。在这种情况下,他可能会决定回滚事务或进行一些清理。 如果您遇到特定异常,请尝试应用相同的规则。我你确切地知道你为什么这样做,然后就是这样做。但在 NPE 的情况下,很少有人想要做一些非常特别的事情。

      【讨论】:

        【解决方案6】:

        如果你有一个优雅的方式来处理你的异常,那么捕获它是有用的,如果不是希望调用者有一个很好的方式来处理它。

        【讨论】:

        • 如果没有,最终可以记录异常。
        猜你喜欢
        • 1970-01-01
        • 2015-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-03
        • 2012-08-22
        • 1970-01-01
        相关资源
        最近更新 更多