Java样式:正确处理异常


问题内容

我一直在概念上为我的项目决定异常处理结构。

假设您有一个示例:

public abstract class Data {
   public abstract String read();
}

还有两个子类FileData和StaticData,它们从某些指定的文件中读取数据,StaticData仅返回一些预定义的常量数据。

现在,在读取文件时,可能会在FileData中引发IOException,但是StaticData将永远不会抛出。大多数样式指南建议在调用堆栈上传播Exception,直到有足够的上下文可以有效处理它为止。

但是我真的不想在抽象的read()方法中添加throws子句。为什么?因为数据和使用它的复杂机器对文件一无所知,所以它对数据一无所知。此外,可能还有其他Data子类(以及更多子类)永远不会抛出异常并完美地传递数据。

另一方面,IOException是必需的,因为如果磁盘不可读(或某些此类),则 必须
引发错误。因此,我看到的唯一出路是捕获IOException并在其位置抛出一些RuntimeException。

这是正确的哲学吗?


问题答案:

你是对的。

异常应该与所使用的抽象级别相同。这就是自Java 1.4
Throwable开始支持异常链接的原因。例如,对于使用数据库的服务或与“存储”无关的服务,都没有必要抛出FileNotFoundException。

可能是这样的:

public abstract class Data {
   public abstract String read() throws DataUnavailableException;
}

class DataFile extends Data { 
    public String read() throws DataUnavailableException {
        if( !this.file.exits() ) {
            throw new DataUnavailableException( "Cannot read from ", file );
         }

         try { 
              ....
         } catch( IOException ioe ) { 
             throw new DataUnavailableException( ioe );
         } finally {
              ...
         }
 }


class DataMemory extends Data { 
    public String read()  {
        // Everything is performed in memory. No exception expected.
    }
 }

 class DataWebService extends Data { 
      public string read() throws DataUnavailableException {
           // connect to some internet service
           try {
              ...
           } catch( UnknownHostException uhe ) {
              throw new DataUnavailableException( uhe );
           }
      }
 }

请记住,如果您在编程时考虑到继承,则应针对特定方案进行仔细设计,并使用这些方案测试实现。显然,编写通用库比较困难,因为您不知道如何使用它。但是,大多数情况下,应用程序都局限于特定的领域。

您的新异常是运行时还是已检查?这取决于一般规则是抛出运行时错误并检查可恢复条件。

如果可以通过正确编程避免异常(例如NullPointerException或IndexOutOfBounds),请使用运行时

如果异常是由于程序员无法控制的某些外部资源(例如,网络已关闭)引起的,并且可以执行某些操作(在5分钟内显示重试消息等),则应使用已检查的异常。

如果该异常不受程序员的控制,但是可以执行NOTHING,则可以使用RuntimeException。例如,您应该写入文件,但是该文件已被删除,并且您无法重新创建或重试该文件,则该程序很可能在运行时失败(您无能为力)。

请参见有效Java中的以下两项:

  • 将检查的异常用于可恢复的条件,将运行时异常用于编程错误
  • 抛出适合抽象的异常

我希望这有帮助。