java - 是否可以解决不使用更广泛的异常“System.Exception”的问题?

标签 java exception exception-handling

我很新鲜,在成功完成项目后,我通过设防扫描了它。它给了我一个问题清单,其中只剩下一个类别。 (强化代码质量扫描工具)

它说:“除非有某些条件,否则不要使用更广泛的异常,即System.Exception”来捕获异常。

但是我有一些方法具有25-30行代码,这些代码具有不同类型的操作,在这种情况下,如何确定要捕获哪些特定异常。

我是否应该将所有这些异常都抛出来以更高的级别捕获,如我读到的“ throw first catch late late”。

请为我建议一种干净的方法。

例如

public SomeMethod(arg) throws IOException,SQLException,beanNotFoundException { 
    try {
        someCode
    } catch (IOException|SQLException|beanNotFoundException ex) {
        logger.log(ex);
        throw ex;
    }
}


但是如果我直到最后都不使用异常类,那么我还必须确保我不会丢失任何异常要处理。

有没有更好的方法。

最佳答案

静态分析

首先,让我从大多数人容易遭受的一个谬论开始(我在企业界看到了很多):静态分析工具并非万无一失。他们犯错误。有一些警告类别,在人类已知的所有计算能力以及整个宇宙的剩余寿命中,该工具可能无法详尽分析与特定警告类别有关的一段代码。此外,有些警告类可以在时间结束之前完成,但是期望您等7天才能为一条执行路径的一段代码等待一个警告,这是不合理的。也就是说,静态分析工具有时必须进行猜测。更好的工具更擅长猜测(您为获得的结果付费),但最终,它们都能够猜测对(真阳性/阴性)或错(假阳性/阴性)。

此外,某些警告类别可能适用,而某些警告类别则无效。其他一些警告类对您可能很重要,而另一些则可能不重要。例如,PMD具有警告类别,表示“未使用的导入”。未使用的导入对运行时没有影响,虽然可能不理想,但是您可以将其保留在代码中,除非您的代码库很大并且需要时间来编译,并且其中有很多(未使用的导入),否则它不会影响您。延长构建项目的时间)。我特别提到静态分析,因为听起来好像您在代码库上运行了Fortify并修复了所有问题,而没有质疑有效性。在大多数情况下,它可能是正确的,只是不要将其视为事实,因为它告诉了您。您需要质疑这些工具是否总是正确的。

你的例子

因此,您的例子不是假阳性。如果你这样做

throw new Exception("");


那通常不是你想要做的。非常适合调试,并且可以快速将代码放在一起。但是,随着您的代码库变大,处理Exception会变得更加困难。

这将我引向下一点。你发表声明


  但是我有一些方法具有25-30行代码,这些代码具有不同类型的操作,在这种情况下,如何确定要捕获哪些特定异常。
  
  ...
  
  但是如果我直到最后都没有使用异常类,那么我还必须确保我不会遗漏任何要处理的异常。


这似乎向我表明,您要么具有某些影响

try{
  //25-30 lines of code
} catch (Exception ex) { /*ex.printStackTrace(); Logger.getLogger(...).log(...); etc etc...whatever it is you do here, or maybe nothing at all*/


这非常糟糕-在大多数情况下。

在我解释原因之前,要先回答您的问题,是的,您应该绝对捕获每个单独的异常。造成这种情况的原因以及导致全部失败的原因是,如果出现某些特定的错误,您将无法进行特定类型的错误处理。

例如,使用一个Foo#bar(java.lang.String)函数,该磁盘由于您试图写入错误的文件而导致磁盘访问失败时抛出IOException;如果传入的字符串中没有特殊字符,则抛出BooException;否则,抛出BazException。任意理由。现在,让我们从上方回到您的示例:如果我想知道正在写入的文件是坏的,并且可能在我继续之前提示用户进行一些澄清,该怎么办?如果我知道如果抛出了BooException,那该用户应该根本不在这里,而我需要将他们重定向到某个位置怎么办?如果我知道当BazException某个系统与某些其他系统不同步并且这是一个致命问题,并且现在我需要在强制使JVM崩溃之前进行资源清除,该怎么办?

上面的原因是为什么您应该对每个语句和每个异常执行单独的try / catch块。

话虽如此,有理由不这样做。想象一下,在上面的示例中,您要为IOException,BooException和BazException(以及任何运行时异常,即NullPointerException)要做的一切只是我想记录该异常并继续前进。在这种情况下,我想对代码块进行尝试/捕获是可以的-只要是在适用于此代码的范围内。

编辑:您提出了关于遗漏异常的观点,但是在评论中对此做出回应似乎并不守法。无论如何,让我首先说一下它是否不是运行时异常,那么即使不处理它也将无法编译。捕获Exception捕获所有内容,无论是否运行时,这都是您现在进行的编译方式。在上面的示例中,如果存在运行时异常,您担心会丢失,而不是仅仅从捕获Exception开始:

Foo myFooInstance = new Foo();
String someValue = "value";
try {
  myFooInstance.bar(someValue);
} catch (IOException ioe) {
  /*handle file access problem*/
} catch (BooException boe) {
  /*handle user in wrong spot*/
} catch (BazException bze) {
  /*handle out-of-sync fatal error*/
} catch (Exception ex) {
  LogRecord lr = new LogRecord(Level.SEVERE, "Unhandled exception!! returning immediately!!");
  lr.setThrown(ex);
  lr.setParameters(new Object[]{someValue});
  Logger.getLogger(MyClass.class.getName()).log(lr);
  return;
}


在这里,您将以万能的结尾而不是从头开始。将其视为您尝试处理所有事情的最后努力。这可能并不意味着该异常对您的程序致命,但是您也不应该继续执行此操作(因此,为什么我的示例使用return;

另一个需要考虑的小问题是,尝试块越大,JVM正确捕获异常的难度就成倍增加(如果从未抛出异常,则不会产生开销)。对于功能强大的机器而言,这是微不足道的,但要记住一点。考虑到这一点,对于在大型try块中引发的异常,我也没有任何性能方面的信息,因此除非有人发现并提及它,否则请花点精力。

关于java - 是否可以解决不使用更广泛的异常“System.Exception”的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32365263/

相关文章:

java - 我在尝试访问 REST Web 应用程序时收到 404 错误

java - 更改可扩展 ListView 的默认图标

java - Jersey 客户端和 com.sun 包

java - doThrow 异常不抛出 Spring MVC 单元测试?

c++ - 是否有一种模式可以依次执行多个 throw 函数?

java - itextPdf 的问题,拒绝重新初始化先前失败的类 java.lang.Class<com.itextpdf.awt.PdfGraphics2D>

java - 这个异常是在哪里捕获和处理的?

java - 在某些情况下处理 RuntimeExceptions 有效吗?

java - 为什么这些重新抛出的异常中的任何一个都会产生编译器错误?

java - 处理从自定义转换器抛出的 Spring Boot REST 中的异常