[英]Best practice for Java exception handling
我最近写了下面的代码; 它使用了很多异常处理。 我认为它使代码看起来非常难以理解。 我可以通过捕获泛型异常来缩短代码,例如
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());
}
}
}
我想知道是否有更好,更清晰的方法来捕获多个异常。
首先,除非你有很好的理由, 永远赶不上RuntimeException
, Exception
或Throwable
。 这些将赶上抛出任何东西,和Throwable
会抓住一切 ,即使是那些你不打算赶,喜欢的东西OutOfMemoryError
。
其次,避免捕获运行时异常,除非它直接阻碍程序的关键操作。 (但严重的是,如果有人看到你发现了NullPointerException
,那么他们完全有权在你身上打电话给你。)你唯一需要注意的例外是那些你需要处理的例外。 在您的异常列表中,您唯一应该打扰的是IOException
。 其余的是没有足够的测试或草率编码的结果; 那些不应该在您的应用程序的正常运行时间内发生。
第三,在Java 7中,如果异常是互斥的,您可以为异常执行多捕获语句。 链接的示例很好地解释了它,但如果您遇到同时IOException
和SQLException
,您可以像这样处理它:
try {
// Dodgy database code here
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
这会清理一些事情,因为你没有笨拙和庞大的异常链。
首先,“最佳实践”建议的问题在于它倾向于过度简化问题和答案。 然后有人(像你一样)出现并注意到它是矛盾的。
国际海事组织,最佳做法是采取“最佳做法”建议和经常使用该词组的人怀疑健康。 尝试自己理解真正的问题,并得出自己的结论......而不是仅仅依靠别人告诉你什么是“最佳实践”。
那么这里的问题是什么? 这是声明:
但我也听说过捕获一般异常不是一个好的编码实践。
实际上,捕获像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的对应点是:
正如您所看到的,这比“捕获通用异常是不良做法”更加微妙。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.