我应该在方法声明中提到哪些例外,以及我应该在catch块中捕获哪个例外?

时间:2012-07-17 19:32:08

标签: java exception exception-handling core

让我们说我们有以下条件。

A)

public void method() throws ... {

      XXXXXXXXXXXXXXXXXXXXXXX;
}

B)

public void method(){

  try{

      XXXXXXXXXXXXXXXXXXXXXXX;
   }catch(...){

      //doing something here
   }

}

假设标有"XXXX"的行是可能引发异常的一行代码(假设此行不会引发错误)。

所以我的问题是,我应该在第一种情况下(在方法声明中)提到的例外情况以及我应该在我的catch块中捕获的异常?

*我知道只是抛出和捕获异常异常就足够了,但我认为这不是一个好的设计。 *

4 个答案:

答案 0 :(得分:3)

看起来您似乎在问如何判断给定方法将会或可能抛出的异常。由于您并没有告诉我们您尝试运行哪种方法,因此很难回答。但Java的一部分原因是它是静态类型的,事实上你确实知道任何方法都可以抛出哪些异常。这是一个编译时错误,不能明确地捕获您调用的任何异常方法,因此如果您应该捕获某些内容,您将立即知道。例外情况是RuntimeException和它的子节点,它们故意不属于编译时合同。

通常情况下,RuntimeException不应被捕获,它们表示某种状态,您不应该让您的程序首先进入(例如不检查null }触发NullPointerException)但您可以查看文档以了解您正在使用的方法,以查看它们可能会抛出的内容。例如,String.substring()表示它可能会抛出IndexOutOfBoundsException。通常,您应该提前进行必要的索引检查,但如果您不能提前做到,那么您可以抓住它,如下所示:

int userInputWeCantTrust = -4;
try {
  System.out.println("foo".substring(userInputWeCantTrust));
} catch (IndexOutOfBoundsException e) {
  System.err.println("Looks like I can't trust you, user.");
}

执行此操作时,您希望尽可能明确地使用异常类型(例如,捕获IndexOutOfBoundsException,而不是RuntimeException),并在{{1}中放置尽可能少的代码阻止。否则,您可能会意外捕获应该允许继续传播的异常。


决定抓或扔是一个设计决定。如果你能够处理一个给定的异常,那么你将它包装在try-catch中,如果你不是,你就不会。

示例一,解析整数,失败时默认为try

default

示例二,解析用户输入,让main方法处理错误报告:

public static int parse(String s, int default) {
  try {
    return Integer.parseInt(s);
  } catch (NumberFormatException e) {
    return default;
  }
}

这实际上取决于您的使用案例。

答案 1 :(得分:1)

编译器将为您解答这些问题:您需要捕获代码可以生成的Exceptions将它们声明为您的方法抛出。如果你遗漏了任何内容,编译器会抱怨。 RuntimeExceptions是例外。

您唯一的选择是捕获这些特定异常或使用throws传播它们。这个选择 - Exceptions被抛出,被抓住了,取决于你的特定目标。

您需要熟悉您正在使用的API,并且API方法会抛出API的一部分Exceptions,但如果您错过了一个,那么您的代码将无法编译,你有机会解决它。

答案 2 :(得分:0)

简要说一下:

  1. (a)所有已检查的例外
  2. (b)所有处理的例外
  3. 如果您没有按照become part of the documentation for that method(例如JavaDocs)处理异常,那么将异常标记为抛出是好的:

      

    方法可以抛出的任何异常都是方法的一部分   公共编程接口。那些称之为方法的人必须知道   方法可以抛出的异常,以便他们可以决定要做什么   做他们。这些例外同样是该方法的一部分   编程接口作为参数和返回值。

    对于catch块,主要是确保您正在处理正在捕获的任何异常(至少记录异常消息)。您可能希望尝试从异常中恢复,抛出不同类型的异常或只记录输出:

    E.g。好:

    catch(NullPointerException e) {
        variable = "default-value";
    }
    
    catch(NullPointerException e) {
        throw new OhNoesException();
    }
    
    catch(NullPointerException e) {
        log.warn(e.getMessage());
    }
    

    如果您正在做的只是放弃Exception,那么抛出它会更好。 E,g,Bad(作为一般经验法则):

    catch(NullPointerException e) {}
    

答案 3 :(得分:0)

尝试考虑调用者对您的方法的期望。想想这是你的方法给调用者的“承诺”。

现在,假设您正在调用某些内容,并且您可能会遇到异常。你可能会问自己的问题是:我是否仍能履行我通过处理该异常而做出的承诺,并继续下去?如果你不能:抛出异常(或者,抛出一个不同的异常 - 通过将它包装在MyApplicationException或其他东西中)。

如前所述:这可能是一个设计问题 - 整数解析方法的“承诺”可能是“以最佳方式将字符串转换为数字”,在这种情况下,您不会在任何情况下抛出异常,或者它可以“解析一个应该是整数的正确编码的字符串”;在这种情况下抛出异常将是一个更好的主意。