Java 异常处理的最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32545270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best practice for Java exception handling
提问by Guan Summy Huang
I wrote the following code recently; it uses a lot of exception handling. I think it makes the code look very unreadable. I could shorten the code by catching generic exception, such as
我最近写了以下代码;它使用了很多异常处理。我认为它使代码看起来非常不可读。我可以通过捕获通用异常来缩短代码,例如
catch (Exception e){
e.printStackTrace();
}
but I also heard that catching generic exception is not a good coding practice.
但我也听说捕获通用异常不是一个好的编码习惯。
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());
}
}
}
I would like to know if there is any better and cleaner way to catch multiple exceptions.
我想知道是否有更好、更干净的方法来捕获多个异常。
回答by Makoto
First, unless you have verygood reason, never catch RuntimeException
, Exception
or Throwable
. These will catch most anything that is thrown, and Throwable
will catch everything, even those things you're not meantto catch, like OutOfMemoryError
.
首先,除非你有非常充分的理由,永远也赶不上RuntimeException
,Exception
或Throwable
。这些将捕获大多数抛出的东西,并且Throwable
会捕获所有东西,甚至那些你不打算捕获的东西,比如OutOfMemoryError
.
Second, avoid catching runtime exceptions unless it directly impedes with the critical operation of your program. (But seriously, if anyone sees you catch a NullPointerException
, they are within their full rights to call you out on it.) The only exceptions you should be bothering with are those that you are required to handle. Out of your list of exceptions, the only one you shouldbother with is IOException
. The rest are the result of not enough tests, or sloppy coding; those shouldn't occur in the normal run time of your application.
其次,避免捕获运行时异常,除非它直接妨碍程序的关键操作。(但说真的,如果有人看到你抓到了NullPointerException
,他们完全有权利叫你出来。)你应该烦恼的唯一例外是那些你需要处理的例外。在您的例外列表中,您唯一应该考虑的是IOException
. 其余的都是测试不够,或者编码马虎的结果;这些不应该发生在您的应用程序的正常运行时。
Third, in Java 7, you have the ability to do a multi-catchstatement for your exceptions, if the exceptions are mutually exclusive. The example linked does a good job of explaining it, but if you were to encounter code that threw both an IOException
and an SQLException
, you could handle it like this:
第三,在 Java 7 中,如果异常是互斥的,您可以为异常执行多捕获语句。链接的示例很好地解释了它,但是如果您遇到同时抛出 anIOException
和 an 的代码SQLException
,您可以这样处理:
try {
// Dodgy database code here
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
This cleans things up a bit, as you don't have unwieldy and huge chains of exceptions to catch.
这会稍微清理一下,因为您没有需要捕获的庞大而庞大的异常链。
回答by Stephen C
First of all the problem with "best practice" advice is that it tends to over-simplify the question and the answer. Then someone (like yourself) comes along and notices that it is contradictory.
首先,“最佳实践”建议的问题在于它倾向于过度简化问题和答案。然后有人(比如你自己)出现并注意到这是矛盾的。
IMO, best practice is to take "best practice" advice and people who regularly use that phrase with a healthy level of suspicion. Try to understand the real issues yourself, and reach your own conclusions ... rather than just relying someone else to tell you what is "best practice".
IMO,最佳做法是采用“最佳做法”建议和经常使用该短语的人以健康的怀疑水平。尝试自己了解真正的问题,并得出自己的结论……而不是仅仅依靠别人来告诉您什么是“最佳实践”。
So what's the problem here? It is this statement:
那么这里有什么问题呢?这是这样的声明:
but I also heard that catching generic exception is not a good coding practice.
但我也听说捕获通用异常不是一个好的编码习惯。
In fact, it is not normallygood coding practice to catch generic exceptions like Exception
. But it is the right thing to do in some circumstances. And your example is one where it is appropriate.
事实上,这是不正常良好的编码习惯赶上通用异常喜欢Exception
。但在某些情况下,这是正确的做法。你的例子是一个合适的例子。
Why?
为什么?
Well lets look a case where catching Exception
is a bad idea:
好吧,让我们看看捕捉Exception
是一个坏主意的情况:
public void doSomething(...) {
try {
doSomethingElse(...);
} catch (Exception ex) {
// log it ... and continue
}
}
Why is that a bad idea? Because that catch
is going to catch and handle unexpectedexceptions; i.e. exceptions that you (the developer) did not think were possible, or that you did not even consider. That's OK ... but then the code logs the exception, and continues running as if nothing happened.
为什么这是个坏主意?因为这catch
将捕获并处理意外的异常;即您(开发人员)认为不可能的,或者您甚至没有考虑过的例外情况。没关系……但是代码会记录异常,并继续运行,就好像什么也没发生一样。
That's the real problem ... attempting to recover from an unexpected exception.
这才是真正的问题……试图从意外异常中恢复。
The (so-called) "best practice" advice to "never catch generic exceptions" deals with the issue, but in a crude way that doesn't deal with the edge cases. One of the edge cases is that catching (and logging) a generic exception is OK if you then immediately shut the application down ... like you are doing.
“永远不要捕获通用异常”的(所谓的)“最佳实践”建议处理了这个问题,但以一种不处理边缘情况的粗略方式。边缘情况之一是,如果您立即关闭应用程序……就像您正在做的那样,捕获(并记录)通用异常是可以的。
public void main(...) {
try {
// ...
} catch (Exception ex) {
// log exception
System.err.println("Fatal error; see log file");
System.exit(1);
}
}
Now contrast that with the (supposedly) good practice version in your question. What is the difference?
现在将其与您问题中的(据称)良好实践版本进行对比。有什么区别?
- Your version produces more user friendly / less alarming diagnostics ... up to a point.
- Your version is significantly more code.
- Your version is unhelpful to someone trying to diagnose the problem because the stacktraces are not recorded.
- 您的版本产生了更多用户友好/更少警报的诊断......直到某一点。
- 您的版本代码要多得多。
- 您的版本对尝试诊断问题的人没有帮助,因为没有记录堆栈跟踪。
And the counterpoints to 1 and 2 are:
1 和 2 的对立点是:
- You can spend limitless time honing the "user friendly" diagnostics for an application, and still fail to help the kind of user who can't or won't understand ...
- It also depends on who the typical user is.
- 您可以花费无限的时间来磨练应用程序的“用户友好”诊断,但仍然无法帮助那些不能或不会理解的用户......
- 这也取决于谁是典型用户。
As you can see, this is far more nuanced than "catching generic exceptions is bad practice".
如您所见,这比“捕获通用异常是不好的做法”要微妙得多。