【问题标题】:How to handle an exception in Java thrown by a method into another method?如何处理Java中一个方法抛出的异常到另一个方法中?
【发布时间】:2021-07-27 12:49:12
【问题描述】:

假设我有这个类:

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?

基本上,我可以这样做吗?

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

还是不行?

【问题讨论】:

  • 是的,如果do_SomeOtherThing 也标有throws SomeException,则可以这样做,假设SomeException 实际上是一个检查异常。但是,“异常只能被main 捕获”是非常不正确的。当该方法可以适当地处理异常时,应该捕获异常。
  • 所以基本上我必须在 do_SomeOtherThing 中声明 throws SomeException 而不会有效地抛出任何东西?
  • @Sweeper:这并不总是正确的,但它比让每个方法都捕获东西要好得多。这样程序在第一次抛出某些东西时会快速失败,堆栈跟踪应该指出问题所在。不同类型的应用程序将有不同的地方来捕捉东西,但这是一个好的开始。 AleMaffe:你让它从其他方法中被抛出。
  • @NathanHughes 这就是为什么我如此专注于绝对删除非主要内容中的所有形式的捕获

标签: java exception methods try-catch


【解决方案1】:

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

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

  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 子句会让你很难发现你的代码为什么不能工作。
  • 包装异常时,始终将原始异常作为原因。

【讨论】:

  • 好的,非常感谢。基本上我只需要第一个选项,我的问题只是关于捕获内部方法抛出的异常,无论如何谢谢!
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2013-10-15
  • 2016-04-03
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多