Java:异常处理

5
以下代码不进行转换的原因是什么?
try {
    // Do something
} catch (XException e) {
    e.printStackTrace();
} catch (YException e) {
    e.printStackTrace();
} catch (ZException e) {
    e.printStackTrace();
}

转换为:

try {
    // Do something
} catch (Exception e) {
    e.printStackTrace();
}

我知道第二种方法可以捕获各种异常,而且我不介意。假设我想以相同的方式处理所有异常。那么性能差异是否很大?


1
“性能差异很大吗?”你在分析时得到了什么结果?顺便说一句,健壮、可维护的代码通常值得稍微牺牲一点性能(如果有的话)。 - Andrew Thompson
12个回答

3

这种分离只是为了您能够针对不同的异常执行不同的任务。例如,如果您收到解析异常和IO异常,则会准确知道如何处理每个异常。

在新版本中,通过将多个异常放入一个块中,这些块已经被最小化,这将有助于编码人员并提高可读性。例如:

try {
    // Do something
} catch (XException | YException | ZException e) {
    e.printStackTrace();
}

这将类似于 catch (Exception){...},因为您将对所有3个执行相同的操作。 - Harry Joy
3
是的,这是针对7+版本的。而且上面的代码与catch(Exception){}不同,很抱歉,因为这里没有捕获所有异常,但在Exception的情况下将捕获所有异常。我写这个的原因只是为了解释用新的方式编写相同的内容。 - Talha Ahmed Khan
@Harry - 新的Java 7语法比catch(Exception)更好,因为后者不建议使用,它会导致你的代码捕获运行时异常,而你可能不想捕获例如OutOfMemory之类的异常。最好让JVM处理这个问题。 - Andrew Fielden
@Andrew:毫无疑问,语法更好,但我的意思是,如果你这样写,那么你将失去以不同方式处理单个异常的能力。 - Harry Joy

3
Java的try/catch机制在连续的JVM中得到了高度的调优,因此它们的性能不是你需要明确担心的事情。相反,您应该根据需要以不同方式处理捕获的错误场景来编写这些块。在您的示例中,您只是打印堆栈跟踪,因此捕获特定错误没有好处 - 但是您的用例实际上将确定您是否应该向上或向下滚动这些try/catch块。

2

如果您不确定性能是否是一个真正的问题,那么目前不需要担心它。

如果每种类型的异常都执行相同的操作,您可能希望进行转换以提高可读性,但不要忘记,捕获Exception除了XExceptionYExceptionZException之外还会捕获很多其他东西。是否有一个有用的基类可以代替它们,并且你可以捕获该基类?


2

有时候你可能想在不同的异常情况下执行不同的操作。

即使你不这样做,你仍然可以帮助其他程序员看到完整的图片,而不是把所有的异常都隐藏在一个大的异常中;这也包括捕获所有的运行时异常。


+1 因为第一个注意到过于宽泛的 catch (Exception ...) - Vlad

2
您单独捕获异常的主要原因是您可能希望根据抛出的异常类型执行不同的操作。例如,在解析文件时,您可能希望引发FileNotFoundException或IndexOutOfBounds异常。一个告诉您找不到要解析的文件,而另一个则告诉您在解析过程中出现了问题。单独处理这些异常会更具信息性,因为它们是完全不同的问题。例如,最终用户可能会根据抛出的异常接收不同的错误消息。

1

捕获RunTimeExceptions(如NullPointerException)的方式有所不同。在第二种情况下可以捕获,但在第一种情况下无法捕获。


是的,没错。这是大多数其他回答中缺失的要点。如果OP想要(但实际上并不想要)处理X和Y的方式不同,那么他们对此是正确的,但是这个事实 - 除了第一种情况中列出的那些例外之外还有其他例外 - 这是一个重大的区别。 - CPerkins

1
在绝大多数情况下,您希望异常处理程序尽可能具体,以使您的代码具有弹性,并在出现异常时采取适当的恢复策略。采用一般的异常处理方法是不明智的,因为处理程序必须对任何可能的异常做出反应,这可能会导致代码更容易出错,当捕获到未预期的异常时,处理程序可能无法处理。本质上,具有catch(Exception e)子句的异常处理程序是懒惰的方法。 从我的经验来看,将异常处理程序置于代码块周围的动机是捕获特定的异常或一组异常。因此,在构思时,您已经知道要捕获的异常,为什么要概括并使用Exception类呢? 我建议阅读以下两个内容,以了解专用异常处理的优点: 1.《Effective Java第二版-Joshua Bloch:第9章》 2.Java异常教程:异常的优势

正如许多人指出的那样,是的,您可以按照您的要求执行。但是这里的答案涉及到一个有趣的问题。假设您编写了catch(Exception e)而不是显式捕获每个异常,现在可能会抛出新的异常。当前的catch将捕获该新异常类型,没有编译器警告或任何其他问题会显示出来,让您再三考虑是否应该以不同的方式处理此新异常。(还要记住,几乎任何IDE都可以通过单击鼠标或绑定键(如ctrl-1)立即编写显式catch) - Angel O'Sphere

0

在我看来,这只是一个处理所有错误方式相同或某些错误方式不同的问题。


0

第一种情况适用于您想以不同的方式处理不同的异常,而在第二种情况下,您以相同的方式处理所有异常。当您完全不知道会发生哪种异常时,请使用第二种方法;如果您知道可以使用第一种方法。


0

从技术角度来看,两个版本之间没有太大的区别。第二个版本将捕获所有XYZ异常以及在try块中可能抛出的任何RuntimeException。请检查是否可以接受。

如果catch处理程序对于任何抛出的异常都执行相同的操作,则将它们分组没有问题。虽然在生产代码中通常不会有相同的catch处理程序,但它们通常执行不同的操作或记录不同的消息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,