处理灾难性的例外

时间:2012-11-22 10:03:31

标签: java exception checked-exceptions

我在C#入门书中读到,如果你不知道如何处理它,你不应该发现异常。在使用Java编程时考虑到这些建议,我有时会发现我不知道如何处理异常,但我不得不抓住它或“渗透它”以避免编译错误。我宁愿不要在调用树的整个过程中使用throws子句来混淆方法,所以我经常使用“转换”异常到RuntimeException,如下所示。将throws子句添加到许多方法中以用于未真正“处理”(正确处理)的异常似乎冗长且分散注意力。是以下不好的风格,如果有的话,有什么更好的方法来解决这个问题?

try {
  thread.join();
}
catch (InterruptedException e) {
      Console.printwriter.format("%s\n", e.printStackTrace());
  throw new RuntimeException();
}

编辑:除了杂乱之外,渗透异常还有另一个问题:在代码修订之后,你可能最终会得到一些不必要的throws子句。我知道清除它们的唯一方法是通过反复试验:删除它们并查看编译器是否抱怨。显然,如果您想保持代码清洁,这很烦人。

4 个答案:

答案 0 :(得分:5)

已检查和未检查的例外之间的Java划分为somewhat controversial

如果您控制接口,那么在签名中添加throws子句通常是最好的方法。

如果您处于无法处理异常的情况,但由于检查了异常签名而不允许它冒泡,那么将异常包装到可以重新抛出的异常中(通常是RuntimeException)常见的做法。

在许多情况下,您希望使用另一个已检查的异常,例如IOException或SQLException。但这并不总是一种选择。

但在您的示例中,将原始异常包含为“原因”:

 throw new RuntimeException(e);

这也可以消除对日志记录的需要(因为这也可以推迟到可以处理异常的人,并且所有信息仍然存在)。

答案 1 :(得分:1)

如果您不知道如何处理异常,则不应该抓住它。因此,您的方法现在将抛出异常,因此如果它不是运行时异常,它应该有一个throws子句。他们没有错。

答案 2 :(得分:1)

我喜欢Joshua Bloch的Effective Java 2nd edition中的建议 - 抛出适合抽象的例外(第61项)。

也就是说,当你面对一系列例外时,你希望从你的方法中“渗透”出来,考虑是否应该用对你的方法更具语义意义的东西重新包装异常。

这种方法通常会产生令人愉悦的副作用,即将几个较低级别的异常组合成单个较高级别的异常。

答案 3 :(得分:1)

良好的编程实践告诉您应该隐藏对象的内部状态,至​​少对我来说,还包括异常。您应该看到该异常的含义是什么,并向您的类的调用者返回表示该含义的异常。

如果框架已经提供了具有该含义的异常,例如IllegalArgumentException,则应该实例化一个新对象,给它一个字符串,其中包含对所发生事件的良好描述并封装所引发的异常,这与新的IllegalArgumentException类似( "由于......",e),参数X无效; 如果框架没有针对您的问题的良好描述性异常,您应该创建自己的一组例外。我通常为该项目/包创建一个通用异常(它将扩展Exception或RuntimeException)并从中派生异常。 例如,我最近创建了一个通用存储库项目,可以在我们的服务和应用程序模块中重用以访问数据库。由于我想从我用来访问数据库的抽象工具中抽象出来,即使是异常,我最终还是创建了一些例外来封装JPA Hibernate异常。我这里没有代码,但它类似于:

// implementation package
public abstract class GenericRepository<K, E extends<K>> implements IRepository<K, E>{

    //  constructors

    public final void add(E entity){
        // some code

        try{
            //  code that can throw exceptions
        } catch (EntityExistsException e) {
            //  some code
            throw new EntityAlreadyExistsException(e);
        } catch(RuntimeException e) {
            //  some code
            throw new GenericRepositoryException("An unexpected exception occurred while manipulating the database", e);
        }
    }

    //  some other code

}


// exception package
public final class EntityAlreadyExistsException extends GenericRepositoryException{

    public static final String GENERICMESSAGE = "The entity already exists on the table";

    public EntityAlreadyExistsException(Throwable cause){
        super(GENERICMESSAGE, cause);
    }

    //  other constructors

}
相关问题