打印有关异常的所有信息吗?

时间:2018-07-12 12:40:14

标签: java exception exception-handling

我正在开发一些后台程序,该程序有时会执行“某些操作”。但是,“某事”可能出错了,我想写一个日志,以便我可以找出问题所在,并且可能有不同的错误原因。我使用的是封闭源代码库(目前没有可用的文档),并且我不知道所引发的异常的结构,并且stacktrace无法为我提供足够的信息。

问题:对于不希望“知道”的异常类,通常如何使“所有可能的信息”可见?

即有什么方法可以使异常在没有任何进一步知识的情况下进行自我解释?

示例(警告,冗长:-)):

让我们考虑以下银行帐户示例。该帐户具有一个提供“提取”功能的函数,该函数显然(或者应该让我遗憾地说)抛出InsufficientFundsException异常:

public class Account {
   [...]
   private double balance;
   public void withdraw(double amountWithDraw) throws InsufficientFundsException {
      if(amountWithDraw <= balance) {
         balance -= amountWithDraw;
      } else {
         throw new InsufficientFundsException(balance, amountWithDraw);
      }
   }
}

和异常类看起来像

public class InsufficientFundsException extends Exception {
   private double balance;
   private double amountWithDraw;

   public InsufficientFundsException(double balance, double amountWithDraw) {
      this.amountWithDraw = amountWithDraw;
   }

   public double getBalance() {
      return amountWithDraw;
   }
   public double getAmountWithDraw() {
      return amountWithDraw;
   }
}

现在在主调用代码中,我可能会做类似的事情

try {
  account.withdraw(amountWithDraw);
} catch (InsufficientFundsException e) {
  System.out.println("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
}

在此之前,一切都很好,但是我们可以说主代码有很多不同的“要求”(加钱,减钱,向信息发送该帐户包含多少钱,...)。这些请求中的每一个都可能具有不同的可能失败情况,例如AddMoneyException,NetworkUnreachableException等,因此主代码看起来像

try {
  handleRequest(...);
} catch (InsufficientFundsException e) {
  System.out.println("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
} catch (NetworkUnreachableException e) {
  System.out.println("Network unreachable.");
} catch (AddMoneyException e) {
  ...
} and so on and so on

因此,一方面,代码变得非常笨拙(我需要通过调用函数堆栈拖动许多不同的Exception),另一方面,我不知道异常AddMoneyException和NetworkUnreachableException(除了它们的名称之外)我不知道如何找到无法访问网络或为什么我们无法向该帐户添加一些资金的原因。

所以我认为在抛出异常时分派异常,然后创建一个新的异常'RequestFailedException',这样可以将其统一处理是一个好主意:

try {
  handleRequest(...);
} catch (RequestFailedException e)
  System.out.println("Request failed. Reason=" + e.getReason());
}

现在撤回功能如下:

public void withdrawUnified(double amountWithDraw) throws RequestFailedException{
  try {
    widthDraw(amountWithDraw);
  } catch (InsufficientFundsException e) {
    throw new RequestFailedException("Tried to reduce " + e.getBalance() + " by " + e.getgetAmountWithDraw() + " but taking this much amount of money from the account is not possible!");
  } catch (NetworkUnreachableException e) {
    throw new RequestFailedException("Network is unreachable!");
  }
}

所以我需要以某种方式将所有可能的异常转换为包含有关异常的所有信息的字符串(即还有“自定义属性”,例如balance和amountWithdraw,而不仅仅是StackTrace)。但是,我不知道/不必猜测这些属性。是否有一个统一的函数,它会像toString一样被覆盖?只是做

public void withdrawUnified(double amountWithDraw) throws RequestFailedException{
  try {
    widthDraw(amountWithDraw);
  } catch (Exception e) {
    throw new RequestFailedException("Exception=" e);
  }
}

不起作用,因为这只会打印出堆栈跟踪的第一行。

谢谢+谢谢,

固件

2 个答案:

答案 0 :(得分:1)

您在这里混淆了两件事:

    首先,
  • 例外是用于传达特定问题的性质的编程方式。
  • 另一方面,
  • 也希望使用它们从中为用户派生有用的消息。

真正的解决方案是退后一步,明确区分这两个问题。例如,您可以执行的操作:创建自己的异常基类,并向其中添加方法,例如getErrorMessageForUser()。现在,您的每个子类都可以提供特定的,易于理解的错误描述。

同时,您的顶级代码仅捕获该特定异常,然后才能使用来自异常的消息。

(我建议不要使用内置的异常消息。至少在较大的系统中,您很快就会开始考虑国际化,例如:如何确保以用户的特定语言给出错误消息)

答案 1 :(得分:1)

如果您还打算使用自定义异常作为消息载体,那么我建议做的是重写类中的getMessage以反映您要对失败原因说什么:

IF(AND(OR

在您的代码中:

public class InsufficientFundsException extends Exception {
   private double balance;
   private double amountWithDraw;

   public InsufficientFundsException(double balance, double amountWithDraw) {
      this.amountWithDraw = amountWithDraw;
   }

   public double getBalance() {
      return amountWithDraw;
   }
   public double getAmountWithDraw() {
      return amountWithDraw;
   }

   public String getMessage() {
      "Tried to reduce " + balance() + " by " + amountWithDraw() + " but taking this much amount of money from the account is not possible!"
   }
}