【问题标题】:Is it good to catch a more general type of Exception?捕获更一般类型的异常是否很好?
【发布时间】:2009-05-21 19:34:54
【问题描述】:

如果我们要捕获特定形式的 IOException 或任何其他形式的 事实上,我们只尝试抓住几个(并为他们定义明确的输出)说

FileNotFoundException
ZipException

我们是否应该一直跟踪它并用

覆盖所有基地
catch(IOException e){
    e.printStackTrace();
}

然后可能会走得更远,抓住Exception e,或者这是一个 完全浪费时间?

【问题讨论】:

    标签: java exception-handling


    【解决方案1】:

    通常,您只想捕获和处理可以在低级别执行某些操作的异常。然后在更高级别上,捕获系统范围内所有未处理的异常,以便记录发生的错误。

    【讨论】:

      【解决方案2】:

      通常,您应该只捕获要明确处理的异常。

      您不应该捕获 Exception、IOException 等。 al.,除非你是一个适当的高级别,你正在执行最后一次抓包以向用户报告一般错误。

      【讨论】:

        【解决方案3】:

        如果有疑问,总是捕获更具体的异常!

        【讨论】:

          【解决方案4】:

          您捕获的异常层次越高,如果没有正确处理它们或重新抛出它们,您将越多的问题隐藏在地毯下。您可能会遇到难以跟踪的静默错误。

          所以只捕获适当的异常,让其他异常通过。在顶层,如果你不想让你的程序崩溃,你可以有一个包罗万象,但至少记录它。这仍然是一个值得怀疑的方法,因为您的应用程序可能处于不一致的状态,并且您可能会损坏您的数据。

          但要直接回答您的问题,IOException 可能处于适当的级别。让你知道无论是什么问题,它都与 IO 有关,你就可以根据它来行动。没有更多信息很难说。

          【讨论】:

          • Re: 不一致的状态,我相信 finally 块总是在 Java 中执行,因为异常在堆栈中飞升,无论是否捕获到异常。因此,即使您小心不要捕获“致命”异常以避免在处于不一致状态时执行,您也无法停止 finally 块的执行。所以 IMO 这是 JRE 中的一个有争议的问题,除非你避免使用 finally 块,这似乎是一件不得不放弃的可怕事情。 .NET CLR 是不同的 - 如果存在未处理的异常,您可以选择在 finally 块运行之前中止。
          【解决方案5】:

          盲目地捕获任何类型的异常都不是一个好主意。是的,作为一个父异常,它似乎提供了一层“保护”,但这有几个原因是不好的:

          检查 IOExceptions。如果代码中没有任何地方抛出它,那么添加一个不需要的 catch 只会使事情变得模糊,并且可能会使以后查看代码的人感到困惑。

          更重要的是,您不会为了让它们消失而捕获异常。如果他们这样做了,您可以将所有方法包装在 (catch(Exception e){..}) 中并完成它。您的异常捕获代码应该是您决定如果这些错误发生时该怎么做的地方,例如

          catch(FileNotFoundException e)
          {
           log.error("where's the file?");return null;
          }
          catch(ZipException e)
          {
           log.error("corrupt");return null;
          }
          

          关键是要使该方法在所有可能的条件下都表现良好。调用者然后处理,例如,文件内容或没有内容,而不用担心内容是如何到达那里的。

          【讨论】:

          • 不要对此感到厌烦;但是当我看到这个时,我认为这会在其他地方导致 NPE。
          【解决方案6】:

          就像一个优秀的顾问一样,我会说“这取决于。”

          一般而言,在 Java 中,您可以清楚地了解代码中特定点的所有可能异常可能是什么。看到有人使用并不少见

          } catch (Exception e){
             // log or stack trace
          }
          

          ... 在或多或少的一次性代码中。不过,一般来说,您不应该捕获不知道如何有效处理的异常。 (永远,永远永远,做catch (Exception x) ;,即,扔掉异常。永远。)

          控制的事情是问“我能用这个做什么?”通常,可以通过询问用户文件的去向来处理文件未发现异常。 zip 文件异常更难处理。因此,您可能希望有单独的行为。

          另一方面,如果它是一个命令行程序,在任何一种情况下,您可能只需要一条错误消息。

          另外一点建议;不要在“面向客户”的代码中输出堆栈跟踪——非程序员可能会看到的代码。非程序员倾向于查看堆栈跟踪和恐慌的完整性。最好将异常转换为“找不到文件'文件名'”这样的消息。而且,如果您真的想要堆栈跟踪,请使用日志记录将其发送到调试级别输出。

          【讨论】:

            【解决方案7】:

            我认为这是个人喜好问题。就个人而言,这似乎不是一个好的选择。我更喜欢用 try-catch 的东西来编写对我有意义的代码。这意味着尽可能具体。我会说:

            try{
                //Code Here
            }
            catch(FileNotFoundException e){
                //Code Here
            }
            

            【讨论】:

              【解决方案8】:

              您不应在可能发生 IOException 的每个可能位置捕获这些,而是​​应在准备处理剩余 IOException 和一般异常的调用树的更上方。

              我们使用经验法则,即您在可以处理错误的地方捕获特定异常并将剩余的异常传递给调用者。

              【讨论】:

                【解决方案9】:

                我会回显“捕获最具体的异常”。

                我通常会捕获 IOException 并显示某种“读取文件错误”消息,然后允许用户选择另一个文件或任何合适的文件。如果文件真的很糟糕,用户可能对此无能为力,但至少你可以让他们知道文件很糟糕。

                如果你得到一个 FileNotFoundException ,真正的问题几乎可以肯定是用户选择了错误的文件名或硬编码的文件名不再有效。我经常为此显示消息。

                我几乎从不捕获“异常”。你打算怎么办呢?您几乎无法从“出现问题但没有更多详细信息”中恢复过来。在某些情况下,我认为您至少可以显示一条错误消息,而不仅仅是死亡,但仅此而已。

                【讨论】:

                  【解决方案10】:

                  这取决于更具体的异常是否有助于解决问题。有时,就像 JMX 一样,最好只捕获父异常以避免出现一长串可能的子异常。至少 Java 7 将允许我们在每次捕获时拥有一个以上的异常。这将清理代码相当多。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-01-03
                    • 2019-05-06
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-11-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多