try catch块创建干净代码的最佳实践是什么?

可能重复:
JAVA或C#中的exception管理的最佳实践

我今天早些时候在stackoverflow上读过一个问题 ,它让我思考处理exception的最佳实践是什么。

所以,我的问题是处理exception以产生干净和高质量代码 的最佳实践什么

这是我的代码,我认为它很安静,但如果我错了或不清楚,请告诉我! 我试图在方法中牢记可测试性和相同的抽象级别。

每一条建设性意见都受到欢迎。 🙂

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; /** * 

This is a dummy code.

* 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 private interface PointList extends List {} /** * 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 loadPointList(final String path) { Preconditions.checkNotNull(path, "The path of the file cannot be null"); List 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 readPointList(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException { final Object object = objectInputStream.readObject(); List 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"); } }

编辑:

我想避免的是在彼此之后写下大量的捕获案例……

乍一看有些建议:

  1. 你不应该捕获Throwable ,而是尽可能捕获exception。 捕获Throwable的麻烦在于它将包括像OutOfMemoryError之类的Error类。 你想让那些通过(他们因为一个原因而未经检查)。
  2. 记录exception时, 总是传递exception,而不仅仅是toString() 。 没有堆栈跟踪就很难诊断出问题。
  3. 您可能不希望使用常规exception处理方法。

因此,在您捕获exception的地方,您需要这样的东西:

 } catch (IOException e) { logger.error("some relevant message", e); // now handle the exception case } 

如果可能,该消息应包括一些上下文信息。 当有人在搜索日志时,任何可能有助于追踪问题的东西。

对于我不打扰的检查exception,我总是使用org.apache.commons.lang.UnhandledException。

例如

 /** * Calls Thread.sleep(millis) */ public static void threadSleep(final long millis) { try { Thread.sleep(millis); } catch (final InterruptedException e) { throw new UnhandledException(e); } } 

始终抓住可能的最具体的exception – 否则永远不会抓住扔掉。

对我来说最重要的是你从来没有一个空的catch块 – 其中一个可能需要花费大量的时间来查找try中的内容是否实际抛出exception。

我个人希望尽快删除已检查的例外情况,并在可能的情况下用前/后条件检查替换它们。 与未经检查的exception相同 – 但是未经检查的exception实际上是一种非常好的方法来指示程序员错误,如参数检查以确保对象状态(虽然断言可能更好)

您可以选择一些选项。

  1. 使用exception的最重要的一个优点是,您可以拥有所有情况的唯一exception处理程序。 编写代码时,应首先考虑function,然后再考虑exception处理。 因此,您可以在某些地方跳过try / catch以查找未经检查的exception,并将您的方法声明为throws SomeCheckedException以检查已检查的exception。 这允许您拥有最少数量的exception处理程序。

  2. 如果您不知道究竟如何处理exception,请重新抛出它。

  3. 如果捕获已检查的exception,但不希望使用代码的客户端必须处理exception,则可以将exception更新检查为未选中。 (Hibernate通过这种方式处理exception。它们捕获已检查的sqlexception并抛出未经检查的exception而不是这个)
  4. 如果之前的建议对您不方便,那么您也可以选择一些选项:
    • 您可以只添加日志记录并重新抛出相同的exception
    • 您可以通过使用initCause()方法抛出新exception来使用exception链
    • 您可能认为调用代码的代码不应该知道有关原始exception的任何信息,您可以通过创建新exception或使用fillInStackTrace()方法对其进行归档。
  5. 关于抓住Throwable。 是的,你不应该抓住它的方法。 但通常情况下,使用您的程序的客户端根本不需要查看exception,因此,您可能会在链中的顶级exception处理程序中捕获Throwable。