如何处理一个方法抛给另一个方法的Java中的异常?

How to handle an exception in Java thrown by a method into another method?

假设我有这个 class:

public class Obj1{

...

 public void do_Something(int someParameter) throws SomeException {
     if(...) throw new SomeException();
...
 }
...
}

然后,某处

public class Obj2{
...
  public void do_SomeOtherThing(Obj1 obj1){
    obj1.do_Something();
    //apparently the only solution is try-catching it directly, even if I'm not in the main...
...
}

我了解到异常只能由METHOD抛出,由MAIN捕获,所以,我的问题是:try-catch是处理子方法异常的唯一方法,还是最外部的方法(do_SomeOtherThing) 会抛出,这样我就可以直接在main中try-catch了,删除Object2中的try-catch class?

基本上,我可以做如下吗?

public static void main(String[] args){
  Object1 obj1 = new Object1();
  Object2 obj2 = new Object2();
  try{
    obj2.do_SomeOtherThing(obj1);
  }
  catch(SomeException e){
   ...
  }
}

要不要?

已检查的异常是方法与其调用者之间的契约的一部分,抛出的异常总是需要以这种或那种方式处理。

正确答案取决于具体情况:

  1. 调用者可以处理的异常:
String getStringFromRemoteServer() throws IOException { ... }

String getConfigString() {
  try {
    return getStringFromRemoteServer();
  } catch (IOException e) {
    LOG.warn("Failed to contact server, using local version.", e);
    return getLocalString();
  }
}

在这种情况下,我们有所需数据的替代来源,因此如果首选方法失败,我们会捕获异常,记录它(以便我们知道我们的网络存在问题)并调用替代方法。

  1. 异常是致命的,我们不希望调用树中更高层的任何函数尝试处理它。
Configuration parseConfiguration(String configString) throws ParseException { ... }

void loadConfiguration() {
  try {
    this.globalConfig = parseConfiguration(getConfigString());
  } catch (ParseException e) {
    throw new RuntimeException("Corrupted config", e);
  }
}

在这种情况下,异常意味着我们应用程序的配置已严重损坏。试图处理这个错误是没有意义的,我们的任何调用者试图处理它也没有意义,所以在 loadConfiguration() 上声明 throws 只会造成混乱。我们将异常包装在 RuntimeException 中并重新抛出它。请注意,我们记录它——会有一些未捕获异常的顶级报告,所以在这里记录它会重复。

parseConfiguration() 抛出检查异常仍然很有价值,因为当我们从交互式配置编辑器调用它时,我们会捕获异常并向用户显示错误消息。

  1. 也许我们的调用者可以处理异常。
int stringToInteger(String s) throws BadNumberException { ... }

String decimalStringToHexString(String s) throws BadNumberException {
  return intToHex(stringToInteger(s));
}

在这种情况下,我们没有改变异常的含义——decimalStringToHexString 正在从字符串转换数字,一种可能的结果是该字符串是非法的。我们的调用者需要意识到这是一个可能的结果,就像 stringToInteger() 的调用者一样,所以我们只需声明异常并让我们的调用者处理它。我们的调用者知道他们在其中使用数字的上下文,因此他们可以决定如何处理异常。

一些规则:

  • 永远不要完全忽略异常(好的,也许是 InterruptedException)。如果你写 try { ... } catch (Exception e) {} 空的 catch 子句将很难发现你的代码为什么不起作用。
  • 包装异常时,始终将原始异常作为原因。