简体   繁体   English

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

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

Let's suppose I have this class:假设我有这门课:

public class Obj1{

...

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

then, somewhere然后,某处

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...
...
}

I've learned that exceptions should only be thrown by METHOD, and catched by MAIN, so, my question is: is try-catch the unique way to handle sub-method exceptions, or the most external method (do_SomeOtherThing) will throw it, so that I can try-catch it directly in main, deleting the try-catch in Object2 class?我了解到异常应该只由 METHOD 抛出,并由 MAIN 捕获,所以,我的问题是:try-catch 是处理子方法异常的唯一方法,还是最外部的方法 (do_SomeOtherThing) 会抛出它,这样我就可以直接在 main 中尝试捕获它,删除 Object2 类中的 try-catch?

Basically, can I do as follows?基本上,我可以这样做吗?

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

or not?或不?

A checked exception is part of the contract that a method has with its caller, and a thrown exception will always need to be handled one way or another.已检查异常是方法与其调用者之间的契约的一部分,抛出的异常总是需要以一种或另一种方式处理。

The correct answer depends on the exact situation:正确答案取决于具体情况:

  1. The caller can handle the exception:调用者可以处理异常:
String getStringFromRemoteServer() throws IOException { ... }

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

In this case we have an alternative source of the data we need, so if the preferred method fails we catch the exception, log it (so that we know a problem exists with our network) and call the alternative.在这种情况下,我们有一个我们需要的数据的替代来源,所以如果首选方法失败,我们会捕获异常,记录它(以便我们知道我们的网络存在问题)并调用替代方法。

  1. The exception is fatal, and we don't want any function higher in the call tree to try to handle it.该异常是致命的,我们不希望调用树中的任何更高层的函数尝试处理它。
Configuration parseConfiguration(String configString) throws ParseException { ... }

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

In this case an exception means that the configuration of our application is fatally broken.在这种情况下,异常意味着我们应用程序的配置被严重破坏。 There is no point in trying to handle this error, and no point in any of our callers trying to handle it, so declaring throws on loadConfiguration() would just be confusing clutter.尝试处理这个错误是没有意义的,我们的任何调用者尝试处理它也是没有意义的,所以在loadConfiguration()上声明throws只会造成混乱。 We wrap the exception in a RuntimeException and rethrow it.我们将异常包装在RuntimeException并重新抛出它。 Note that we don't log it -- there will be some top level reporting of uncaught exceptions, so logging it here would be repetition.请注意,我们记录它——会有一些未捕获异常的顶级报告,所以在这里记录它会重复。

It is still valuable to have parseConfiguration() throw a checked exception, because when we are calling it from the interactive configuration editor we catch the exception and display an error message to the user.parseConfiguration()抛出已检查的异常仍然很有价值,因为当我们从交互式配置编辑器调用它时,我们会捕获异常并向用户显示错误消息。

  1. Maybe our caller can handle the exception.也许我们的调用者可以处理异常。
int stringToInteger(String s) throws BadNumberException { ... }

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

In this case we are not changing the meaning of the exception -- decimalStringToHexString is converting a number from a string, and one possible outcome is that the string is illegal.在这种情况下,我们不会改变异常的含义decimalStringToHexString正在从字符串转换数字,一种可能的结果是该字符串是非法的。 Our caller needs to be aware of that as a possible outcome, just as callers of stringToInteger() are, so we simply declare the exception and let our caller handle it.我们的调用者需要意识到这是一个可能的结果,就像stringToInteger()调用者一样,所以我们只需声明异常并让我们的调用者处理它。 Our caller knows the context they are using the number in, so they can decide how to handle the exception.我们的调用者知道他们使用号码的上下文,因此他们可以决定如何处理异常。

A couple of rules:几条规则:

  • Never completely ignore an exception (OK, maybe InterruptedException).永远不要完全忽略异常(好吧,也许是 InterruptedException)。 If you write try { ... } catch (Exception e) {} the empty catch clause will make it hard to spot why your code doesn't work.如果你写try { ... } catch (Exception e) {}空的 catch 子句将很难发现你的代码为什么不起作用。
  • When you wrap an exception, always include the original exception as the cause.包装异常时,始终将原始异常作为原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM