Java 如果方法使用引发异常的方法,如何正确捕获异常

Java 如果方法使用引发异常的方法,如何正确捕获异常,java,Java,我有一个关于在使用另一个可以抛出异常的方法的方法中捕获异常的问题 public void methodA(File file) { try { } catch (IOException ex) { } } public void methodB() { // do something with the file File file = new File("/example.txt"); methodA(file); } 我是否需要在methodB中创建一个try-and

我有一个关于在使用另一个可以抛出异常的方法的方法中捕获异常的问题

public void methodA(File file) {
  try {
  }
  catch (IOException ex) {
  }
}

public void methodB() {
 // do something with the file
 File file = new File("/example.txt");
 methodA(file);
}

我是否需要在methodB中创建一个try-and-catch块?或者在这种情况下,在methodA中捕获异常就足够了?不,在这种情况下,您不需要在methodB中捕获异常-但是您可能想要,因为methodA可能会在IOException之外抛出其他错误

这取决于您的意图和异常类型-如果您的methodA抛出一个选中的异常,methodB必须捕获它或声明它抛出该异常。如果它是一个运行时异常,methodB可能会捕获它或忽略它。 在大多数TechStack中,检查异常非常罕见,大多数人认为这是一个失败的实验


最后,方法是否需要捕获异常取决于methodB是否能够处理错误?如果是这样,就在那里捕获它——如果不是,就让它冒泡出来,例如,到一个通用错误处理程序,甚至使程序崩溃。没有什么比捕获每个错误并执行错误操作的程序更烦人的了。

你不能,因为异常只能向上移动调用堆栈。如果程序也在异常之后运行方法,那么即使首先创建异常又有什么意义呢


尝试在异常发生时处理异常。如果在创建
文件时可能出现异常
,则应在创建文件的位置处理该异常。否则,确保传入值不是异常的开销就太大了


我建议要么在
methodB
中捕获它,要么将文件名传递到
methodA
中,让它创建
文件
,并捕获任何异常。

这取决于您希望实现的目标

在您的代码示例中,methodA将处理一个异常并继续methodB执行,而不会中断。这可能不是您想要的,因为读取文件时出错,应该妥善处理

最有可能的情况是,您希望将异常冒泡到执行链上,并在相关对象中处理它(例如,一些可以向用户输出错误消息的错误处理程序)

像这样冒泡出您的异常:

public void methodA(File file) throws CustomUserInputException {
  try {
  }
  catch (IOException ex) {
    throw new CustomUserInputException(ex, "Error opening file" + file.getPath());
  }
}
public void methodB() {
 // do something with the file
 File file = new File("/example.txt");
 try {
   methodA(file);
  }
  catch (CustomUserInputException ex) {
    showErrorToAnUser();
    stopStandardProgramExecution();
  }
}
然后在合适的对象中处理它,如下所示:

public void methodA(File file) throws CustomUserInputException {
  try {
  }
  catch (IOException ex) {
    throw new CustomUserInputException(ex, "Error opening file" + file.getPath());
  }
}
public void methodB() {
 // do something with the file
 File file = new File("/example.txt");
 try {
   methodA(file);
  }
  catch (CustomUserInputException ex) {
    showErrorToAnUser();
    stopStandardProgramExecution();
  }
}

可能重复的可能重复:
methodA
不会引发任何异常,因此
methodB
无法捕获任何异常。我无法判断哪个方法实际执行的操作会从上述代码引发IOException。基本上,规则是:低级方法应该声明它们抛出异常,而不是试图捕获它们。在最高级别处理异常。因此,如果
a
调用
b
调用
c
并且
c
做了一些可能引发异常的事情,不要在
c
b
中处理它(通常),在
a
中处理它。你能在
方法a
中处理异常吗,如果发生异常,您希望methodB继续运行,即使
methodA
?如果不是,您可能不应该在
methodA
中处理IOException,而是通过类似的逻辑声明它引发异常,并在
methodB
中处理它,如果您不能在methodB中处理异常,则声明它引发异常。“尝试在异常发生的地方处理异常。”这是不正确的。您希望处理异常,因为您实际上可以以有意义的方式处理它们。这不一定是它发生的地方,更重要的是我认为不应该发送异常进行处理。如果一个异常需要多捕获之外的额外解析/处理,那么您可能不应该使用异常。问题不是捕获,而是您在捕获中所做的事情。对于小型CLI工具来说,一个简单的
log.e(异常)
就足够了,但对于真正的应用程序来说就不够了。我认为这超出了这个问题的范围。我不是在提倡最低限度的捕获,而是在评论如何对异常进行额外处理开始接近流控制。例如,提示用户从
IOExcepton
重新选择输入文件,而不是将问题转移到代码库的另一部分。