【问题标题】:Chaining exceptions, catching exceptions to throw new ones链接异常,捕获异常以抛出新异常
【发布时间】:2016-04-19 14:05:07
【问题描述】:

将以下代码想象为某个程序 (java) 的一部分:

function z(){
try{
  //some code here, that might throw exceptions.
}catch (SomeException | SomeOtherException e){
  //some exception handling here.
}

function y(){
  z();
}

function x(){
  y();
}

如果在函数 z 中抛出异常 SomeException 或 SomeOtherException,那么函数 x 和 y 将无法按预期执行。 我们想编写我们的代码,使函数 x 和 y 知道函数 z 中抛出了异常,并让它们相应地采取行动。 最好的方法是什么?

function z() thrown FunctionZFailedException{
  try{
    //some code here, that might throw exceptions.
  }catch (SomeException | SomeOtherException e){
    throw new FunctionZFailedException();
  }
}

function y() throws FunctionYFailedException{
  try{
    z();
  }catch (FunctionZFailedException e){
    throw new FunctionYFailedException();
  }
}

function x(){
  try{
    y();
  }catch (FunctionYFailedException e){
   //Do something, like alerting user that something went wrong.
  }
}

这是否太过分了,即声明新异常的唯一目的是将其他异常“转发”到更高级别?

我认为我们也可以让 SomeException 和 SomeOtherException 飞起来并在函数 x 中捕获它们。但是 imo 可能会弥补可读性较差的代码,

例如,如果在函数 z 中捕获的异常是 SQLException 和 NoSuchAlgorithmException,并且函数 y 是 login() 函数。然后函数 x 会尝试调用 login(),或者捕获 SQLException | NoSuchAlgorithmException,如果让这些异常简单地飞到最高级别,或者捕获一个 LoginFailedException,如果我们立即捕获每个异常,并让它们抛出新的异常。似乎捕获 LoginFailedException 会使代码更具可读性。

Imo 两种方式都有其缺点(可读性较差的代码与引入许多异常),我想知道经验丰富的 Java 程序员通常如何处理类似的情况。

任何关于异常的一般想法也感谢大家

【问题讨论】:

  • 在大多数情况下,您需要包含原始异常(“原因”):catch (FunctionZFailedException e){ throw new FunctionYFailedException( e ); }

标签: java exception exception-handling checked-exceptions


【解决方案1】:

当您查看您的代码(以及方法和异常的名称)时,会发现这些方法及其引发的异常是否处于同一抽象级别。

如果你有一个 getInputStream() 方法,那么适当的异常应该是一个 IOException。如果在 getDatabaseConnection() 中调用该方法,则应捕获 IOException 并抛出 SQLException。如果你的 saveCustomerToDatabase() 方法需要这个方法,那么你应该抛出类似 ProcessFailedException 的东西。

我不是编写 javadoc 的忠实拥护者,但有时您应该问自己:我能否用同一种语言(即技术语言、业务语言等)为这种方法及其异常编写好的 javadoc? ?如果 saveCustomerToDatabase() -Method 抛出 IOException,您将无法编写 javadoc。

【讨论】:

  • 我不会抱怨
  • 滑到我的鼠标上,现在点击了“+1”。 - 好答案:)
【解决方案2】:

如果您对方法z() 的当前设计感到满意,并且希望方法y()x()“知道”在z() 中发生了不好的事情,那么您可以让z() 重新抛出吞下后的异常。

public void z() {
    try {
        // some code here, that might throw exceptions.
    } catch (SomeException | SomeOtherException e) {
        // handle the exception and then rethrow it
        logger.log("An exception happened in z().");
        throw e;
    }
}

public void y() {
    try {
        z();
    } catch(Exception e) {
        // handle problem with z() and rethrow the exception
        logger.log("An exception happened when calling z().");
        throw e;
    }
}

public void x() {
    try {
        y();
    } catch(Exception e) {
        // handle problem with y()
        logger.log("An exception happened when calling y().");
    }
}

【讨论】:

    猜你喜欢
    • 2013-06-24
    • 2011-06-27
    • 2016-02-17
    • 1970-01-01
    • 2021-09-02
    • 2010-10-03
    • 1970-01-01
    • 2020-02-13
    • 2018-12-17
    相关资源
    最近更新 更多