如果捕获空指针异常不是一个好习惯,捕获异常是一个好的吗?

时间:2011-01-17 18:13:07

标签: java exception exception-handling nullpointerexception

我听说抓NullPointerException是一种不好的做法,我认为这是明智的。让NullPointerException传播到顶部将允许检测出错的东西。但很多时候我看到很多朋友直接捕捉Exception,所以他们不必担心上面代码中可能出现的所有不同类型的异常。这是一个好习惯吗?什么是最好的未处理的其他类型的例外?除此之外,对于我在确定异常来源的特定代码上处理NullPointerException也是有意义的。那么何时处理异常以及什么时候不应该处理它们?什么是可能的最好的例外列表,最好不做处理?

6 个答案:

答案 0 :(得分:24)

口袋妖怪异常处理很糟糕。特别是,如果它是一个空块而你只是吞咽它们。你有特定类型的异常,因为它们实际上是指特定情境中的特定事物(基本上它们告诉你出了什么问题)。因此,通过捕捉Exception你说你不关心那些例外是什么,你不关心发生了什么。这可能不是你想要的。

通常,捕获异常时遵循以下规则:

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

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

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

答案 1 :(得分:8)

抓住NullPointerException被认为是一种不好的做法的“原因”并不是因为当出现问题时你应该让它冒出来!说任何例外都是“最好不要处理”仅基于它的类型似乎是一个坏主意。

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

例如,如果您出于业务原因将其耦合到内部存在错误且偶尔会抛出空指针的API,那么抓住它,做一些事情/通过更好的消息通知用户将是完全合法的。让'null'只是因为有人说“捕获空指针异常是坏的”而没有任何意义!

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

答案 2 :(得分:5)

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

NullPointerException通常是代码中的错误的结果。你怎么能明智地把它固定在一个挡块里呢?

没有被例外困扰是不好的做法。

答案 3 :(得分:3)

一般来说,你应该捕获异常的唯一时间是你能以一些有意义的方式处理它。如果你不能,你应该简单地让它冒泡到顶部并终止进程。例如,您是否可以从NullPointerException或I / O错误中以某种有意义的方式恢复?我想不是。

我的异常处理规则:

  • 一般情况下,不要捕捉异常,除非你能以某种有意义的方式处理它们。
  • 在进程/机器边界捕获异常,记录捕获的异常以及可用的任何上下文并重新抛出它。如果异常是自定义异常,您可以将其包装在对调用进程已知/有用的类型的异常中并抛出它。
  • 您也可以在较低级别捕获异常,其中您拥有最多的运行时上下文,记录异常和关联的上下文,然后重新抛出异常。
  • 重新投掷时,请使用throw ;而不是throw caughtException ;。使用前一种语法可保留原始堆栈跟踪;使用后一种语法会创建一个新的堆栈跟踪,从throw caughtException ;开始 - 您将丢失所有上下文并调用堆栈直到捕获到异常的位置。
  • 如果您这样选择,您可以在较高级别捕获异常并正常终止该过程,记录异常信息以帮助调试和纠正基础问题。

不要将异常用作流量控制机制(如果可能)。例外情况本质上应该是特殊的。相反,premptively,强制调用者的任务结束(前置条件)为您调用的任何方法。

有关详细信息,请参阅Bertrand Meyers的书籍 Object Oriented Software Construction, 2nd ed.

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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