从层次结构中捕获显式异常

时间:2018-05-19 17:02:47

标签: java exception exception-handling

我在一个名为ServiceException的基本异常下有一组例外。这些例外包括服务失败的明确原因 - BadRequestExceptionServiceUnreachableException表示我的类无法自行修复的行为。

这种层次结构看起来像这样:

public class ServiceException extends Exception {
    public ServiceException() { super(); }

    public ServiceException(String message) { super(message); }

    public ServiceException(String message, Throwable cause) { super(message, cause); }

    public ServiceException(Throwable cause) { super(cause); }
}

以及其中一个子类型的示例:

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ServiceUnreachableException extends ServiceException {
    private final String message;
    private final Throwable cause;
}

当我使用它时,我希望有以下结构:

public void doProcess() throws ServiceException {
   ...
}

public void processor() {

  try {
    doProcess()
  } catch (BadRequestException e) {
    // Handle specific exception
  } catch (ServiceUnreachableException e) {
    // etc
  } catch (InvalidApiKeyException e) {
    // ...
  }
}

这使我能够干净地使用catch块来捕获各种异常。似乎Java无法推断doProcess方法通过throws ServiceException显式抛出异常。

这会让我相信我需要做以下其中一项:

public void doProcess() throws BadRequestException, ServiceUnreachableException, InvalidApiKeyException {
   ...
}

public void processor() {

  try {
    doProcess();
  } catch (BadRequestException e) {
    // Handle specific exception
  } catch (ServiceUnreachableException e) {
    // etc
  } catch (InvalidApiKeyException e) {
    // ...
  }
}

public void doProcess() throws ServiceException {
   ...
}

public void processor() {

  try {
    doProcess();
  } catch (ServiceException e)  {
     if(e instanceof BadRequestException) {
       // cast and do stuff
     } else if(e instanceof ServiceUnreachableException) {
       // cast and do stuff
     } else if(e instanceof InvalidApiKeyException) {
        //cast and do stuff
     }
  }
}

对于更清晰的doProcess方法定义来说,这似乎更加混乱。

这里哪个更正确?他们都工作,但我觉得catch版本是你应该如何使用异常,另一个是混乱,因为doProcess决定通过不明确枚举它抛出的所有异常来保存几行

谢谢!

1 个答案:

答案 0 :(得分:0)

  

似乎Java无法推断出异常被抛出   通过name:明确地通过doProcess方法。

不,它不能,因为它无法确信它知道现在存在或将来可能存在的throws ServiceException的所有子类。

  

这里哪个更正确?

这不是正确性的问题。这两种方法都可以完成工作。但我认为捕获一般异常然后使用条件表达式选择特定子类型的行为是不好的风格。您应该使用ServiceException块来将处理程序与特定的例外相关联。

但我认为你提出了错误的问题。请注意,第三种替代方案至少与第一种方案一样好:

catch

当然,假设您要避免public void doProcess() throws ServiceException { ... } public void processor() { try { doProcess(); } catch (BadRequestException e) { // Handle specific exception } catch (ServiceUnreachableException e) { // etc } catch (InvalidApiKeyException e) { // ... } catch (ServiceException e) { // fallback for any other flavor of ServiceException // ... } } 声明任何已检查的异常;否则你也可以拥有它,抛出processor()而不是为它提供一个通用的catch块。

因此,你应该问的问题不是如何抓住而是要扔掉什么。这是一个设计考虑因素,我们没有足够的信息来讨论。