java try catch 块创建干净代码的最佳实践是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5632881/
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
What is the Best practice for try catch blocks to create clean code?
提问by uthomas
Possible Duplicate:
Best practices for exception management in JAVA or C#
可能的重复:
JAVA 或 C# 中异常管理的最佳实践
I've read a questionearlier today on stackoverflow and it made me think about what is the best practice for handling exceptions.
我今天早些时候在 stackoverflow 上阅读了一个问题,它让我思考了处理异常的最佳实践是什么。
So, my question is what is the best practiceto handle exceptions to produce clean and high quality code.
所以,我的问题是处理异常以生成干净和高质量代码的最佳实践是什么。
Here is my code, I think it's quiet straight forward but please let me know if I'm wrong or not clear! I've tried to keep in mind testability and same abstraction level in methods.
这是我的代码,我认为它很简单,但如果我错了或不清楚,请告诉我!我试图记住方法中的可测试性和相同的抽象级别。
Every constructive comment is welcomed. :)
欢迎提出建设性意见。:)
import java.awt.Point;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
/**
* <p>This is a dummy code.</p>
* The aim is present the best practice on exception separation and handling.
*/
public class ExceptionHandlingDemo {
// System.out is not a good practice. Using logger is good for testing too (can be checked if the expected error messages are produced).
private Logger logger = LoggerFactory.getLogger(ExceptionHandlingDemo.class);
// instance of cannot work with List<Point>
private interface PointList extends List<Point> {}
/**
* The method that loads a list of points from a file.
* @param path - The path and the name of the file to be loaded.
* Precondition: path cannot be {@code null}. In such case {@link NullPointerException} will be thrown.
* Postcondition: if the file don't exist, some IOException occurs or the file doesn't contain the list the returned object is {@code null}.
* */
/* (Google throws NullpointerExceptio) since it is not forbidden for the developers to throw it. I know this is arguable but this is out of topic for now. */
public List<Point> loadPointList(final String path) {
Preconditions.checkNotNull(path, "The path of the file cannot be null");
List<Point> pointListToReturn = null;
ObjectInputStream in = null;
try {
in = openObjectInputStream(path);
pointListToReturn = readPointList(in);
} catch (final Throwable throwable) {
handleException(throwable);
} finally {
close(in);
}
return pointListToReturn;
}
/*======== Private helper methods by now ========*/
private ObjectInputStream openObjectInputStream(final String filename) throws FileNotFoundException, IOException {
return new ObjectInputStream(new FileInputStream(filename));
}
private List<Point> readPointList(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
final Object object = objectInputStream.readObject();
List<Point> ret = null;
if (object instanceof PointList) {
ret = (PointList) object;
}
return ret;
}
private void handleException(final Throwable throwable) {
// I don't know the best practice here ...
logger.error(throwable.toString());
}
private void close(final Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
logger.error("Failed closing: %s", closeable);
}
}
}
/*======== Getters and setters by now. ========*/
// ...
/**
* @param args
*/
public static void main(String[] args) {
ExceptionHandlingDemo test = new ExceptionHandlingDemo();
test.loadPointList("test-filename.ext");
}
}
EDITED:
编辑:
What I want to avoid is writing lot of catch cases after each other...
我想避免的是一个接一个地写很多捕获案例......
回答by WhiteFang34
A few suggestions at first glance:
乍一看有几点建议:
- You shouldn't catch
Throwable
and instead catch as specificof an exception as possible. The trouble with catchingThrowable
is that will includeError
classes likeOutOfMemoryError
and the like. You want to let those pass through (they're unchecked for a reason). - When you log exceptions alwayspass the exception and not just its
toString()
. It's very hard to diagnose problems without the stack trace. - You probably don't want a general exception handling method.
- 您不应该捕获
Throwable
而是尽可能地捕获特定的异常。捕获的麻烦Throwable
在于将包括Error
诸如此类OutOfMemoryError
的类。您想让它们通过(出于某种原因,它们未被选中)。 - 当您记录异常时,总是通过异常而不仅仅是它的
toString()
. 没有堆栈跟踪很难诊断问题。 - 您可能不想要通用的异常处理方法。
So at places you catch exceptions you want something like this:
所以在你捕捉异常的地方,你想要这样的东西:
} catch (IOException e) {
logger.error("some relevant message", e);
// now handle the exception case
}
The message should include some contextual information if possible. Anything that might help tracking down the problem when someone is hunting through logs.
如果可能,该消息应包含一些上下文信息。当有人在寻找日志时,任何可能有助于追踪问题的东西。
回答by artbristol
For checked exceptions that I'm not going to bother, I always use org.apache.commons.lang.UnhandledException.
对于我不打算打扰的已检查异常,我总是使用 org.apache.commons.lang.UnhandledException。
For example
例如
/**
* Calls Thread.sleep(millis)
*/
public static void threadSleep(final long millis) {
try {
Thread.sleep(millis);
} catch (final InterruptedException e) {
throw new UnhandledException(e);
}
}
回答by Bill K
Always catch the most specific exception possible--in otherwise never catch throwable.
始终捕获可能的最具体的异常——否则永远不会捕获 throwable。
The most important thing to me is that you NEVER have an empty catch block--one of these can take an amazing amount of time to find if something inside the try actually throws an exception.
对我来说最重要的事情是你永远不会有一个空的 catch 块——其中一个可能需要惊人的时间来查找 try 中的某些内容是否真的抛出异常。
I personally like to remove checked exceptions as quickly as possible and replace them with pre/post condition checks if possible. Same with unchecked exceptions to a lesser degree--however unchecked exceptions are actually a pretty good way to indicate programmer error like parameter checking to ensure object state (Although asserts may be better yet)
我个人喜欢尽快删除已检查的异常,并在可能的情况下用前/后条件检查替换它们。在较小程度上与未检查的异常相同——但是,未检查的异常实际上是指示程序员错误的一种很好的方式,例如参数检查以确保对象状态(尽管断言可能更好)
回答by Alexandr
There some options you can choose.
您可以选择一些选项。
One of the most important adnvantages of exceptions using is that you can have the only exception handler for all cases. When you write your code you should think about functionality first and only then about exception handling. As a result you may skip in some places try/catch at all for unchecked exceptions and declare your methods as
throws SomeCheckedException
for checked exceptions. This allows you to have the minimum number of exception handlers.If you don't know what exactly to do with an exception, just rethrow it.
- If you catch checked exception but you don't want clients that use your code have to process exceptions, you may checked exceptions update into unchecked. (Hibernate processes exceptions by this way. They catch checked sql exception and throw unchecked exceptions instead of this)
- If the previous recommendation are not convenient for your, then you may also choose some options:
- you may just add logging and rethrow the same exception
- you may use exception chains by throwing new exception with initCause() method
- you may think that code that invokes your code should not know anything about the originial exception, you may archive this either by creating new exception or by using fillInStackTrace() method.
- Concerning catching Throwable. Yes in the methods you should not catch it. But as a rule the client that uses your programe need not to see excetpions at all, as a result, you may catch Throwable in the some exception handler that is the top in the chain.
使用异常的最重要的优点之一是您可以拥有适用于所有情况的唯一异常处理程序。在编写代码时,您应该首先考虑功能,然后再考虑异常处理。因此,对于未检查的异常,您可能会在某些地方跳过 try/catch,并将您的方法声明为
throws SomeCheckedException
已检查的异常。这允许您拥有最少数量的异常处理程序。如果您不知道如何处理异常,只需重新抛出它。
- 如果您捕获已检查的异常但不希望使用您的代码的客户端必须处理异常,您可以将已检查的异常更新为未检查的。(Hibernate 通过这种方式处理异常。他们捕获已检查的 sql 异常并抛出未检查的异常而不是这个)
- 如果之前的推荐不方便您,那么您也可以选择一些选项:
- 您可以只添加日志记录并重新抛出相同的异常
- 您可以通过使用 initCause() 方法抛出新异常来使用异常链
- 您可能认为调用您的代码的代码不应该知道有关原始异常的任何信息,您可以通过创建新异常或使用 fillInStackTrace() 方法将其存档。
- 关于捕捉 Throwable。是的,在您不应该捕获的方法中。但是作为规则,使用您的程序的客户端根本不需要看到异常,因此,您可能会在链顶部的某个异常处理程序中捕获 Throwable。