我最近写了以下代码;它使用了很多异常处理。我认为它使代码看起来非常难以理解。我可以通过捕获泛型异常来缩短代码,例如
catch (Exception e){
e.printStackTrace();
}
但我也听说过捕获一般异常不是一个好的编码实践。
public class DataAnalyzerTester {
/**
* @param args args[0] stores the filename
* @exception NoSuchElementException if user attempts to access empty list element
* @exception ArithmeticException if user attempts to divide by 0
* @exception ArrayIndexOutOfBoundsException if user supplied less than 3 arguments
* @exception IOException problems with creating and writing files
* @exception RuntimeException if user attempts to pass empty list to constructor
*/
public static void main(String[] args) {
try{
//some code
} catch (NoSuchElementException e) {
System.out.println("Accessing element that does not exist: " + e.toString());
} catch (ArithmeticException e) {
System.out.println("Division by zero: " + e.toString());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Please supply a command line arguement that specifies your file path: " + e.toString());
} catch (IOException e) {
System.out.println("Other IO errors: " + e.toString());
} catch (RuntimeException e) {
System.out.println(e.toString());
}
}
}
我想知道是否有更好,更清晰的方法来捕获多个异常。
答案 0 :(得分:14)
首先,除非您有 非常 充分理由,永远不会抓住RuntimeException
,Exception
或Throwable
。这些内容会捕获大部分内容,Throwable
会抓住 所有内容 ,即使是那些意味着的内容捕获,如OutOfMemoryError
。
其次,避免捕获运行时异常,除非它直接阻碍程序的关键操作。 (但是说真的,如果有人看到你抓到NullPointerException
,他们完全有权在你身上打电话给你。)你唯一需要注意的例外是那些你需要处理的例子。在您的例外列表中,您应该打扰的唯一一个是IOException
。其余的是没有足够的测试或草率编码的结果;那些不应该在您的应用程序的正常运行时间内发生。
第三,在Java 7中,如果异常是互斥的,您可以为异常执行multi-catch语句。链接的示例很好地解释了它,但如果您遇到同时抛出IOException
和SQLException
的代码,您可以像这样处理它:
try {
// Dodgy database code here
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
这可以清理一些事情,因为你不会有笨拙和巨大的例外链接。
答案 1 :(得分:7)
首先是"最佳实践"建议是它往往过度简化问题和答案。然后有人(像你一样)出现并注意到它是矛盾的。
国际海事组织,最佳做法是采取"最佳做法"建议和那些经常使用这个短语怀疑的人。尝试自己理解真正的问题,并得出自己的结论......而不是仅仅依靠别人告诉你什么是最佳实践"。
那么这里的问题是什么?这是声明:
但我也听说过捕获一般异常不是一个好的编码实践。
事实上,捕捉Exception
等通用异常是通常良好的编码习惯。但在某些情况下这是正确的做法。你的例子就是适当的例子。
为什么?
好吧,让我们看一下捕捉Exception
是个坏主意的案例:
public void doSomething(...) {
try {
doSomethingElse(...);
} catch (Exception ex) {
// log it ... and continue
}
}
为什么这是一个坏主意?因为catch
将捕获并处理意外的异常;即您(开发人员)认为不可能的例外情况,或者您甚至没有考虑过的例外情况。那没问题......但是代码会记录异常,并继续运行,好像什么都没发生一样。
这是真正的问题...... 试图从意外异常中恢复。
(所谓的)"最佳实践"建议"永远不会捕获一般异常"处理问题,但以粗暴的方式处理边缘情况。其中一个边缘情况是,如果您立即关闭应用程序,捕获(并记录)一般异常就行了......就像您正在做的那样。
public void main(...) {
try {
// ...
} catch (Exception ex) {
// log exception
System.err.println("Fatal error; see log file");
System.exit(1);
}
}
现在将问题与(假设的)良好练习版本进行对比。有什么区别?
与1和2的对应点是:
正如你所看到的,这远比#34更加微妙;捕捉一般异常是不好的做法"。