为什么必须在类定义中写抛出异常?

时间:2010-01-05 19:08:28

标签: java exception

来自C#, 我只是没有得到在类/方法定义之后写的'抛出异常':

public void Test() throws Exception

你要写这个吗? 如果你不这样做怎么办? 如果我调用具有此符号的方法,我是否必须捕获它?

9 个答案:

答案 0 :(得分:25)

在所有情况下你都没有来编写它 - 如果你的方法抛出一个被检查的Exception(一个Exception的子类,你只需要写它RuntimeException 1}}而不是bar的子类。这是因为你的方法签名是一个契约,并且它向所有调用它的代码声明它有可能抛出给定的异常。因为它是一个已检查的异常 - 可以预见的异常 - 调用代码需要预测看到抛出异常的可能性,并且需要能够处理它。

回答你的两个具体问题:

  • 你必须写它/如果不这样做:如果你的方法抛出一个已检查的异常,那么是的,你必须在你的方法签名中声明它。如果不这样做,那么您的代码将无法编译。
  • 你必须抓住它:你必须用它来做某事。调用该方法的代码可以捕获它并处理它,它可以捕获它并重新抛出它,或者它可以将它传递给链。为了将它传递给链,调用方法的代码必须自己声明它抛出相同的异常 - 例如,如果方法SomeException可以抛出foo,方法bar调用foo并且不想捕获异常,SomeException的方法签名会声明它也会抛出{{1}}。

Exceptions chapter of the Java lessons非常擅长详细解释这一点,JavaWorld has a good article about throwing and catching exceptions我总是发现这是传递给人们的好参考。

答案 1 :(得分:7)

基本上是的,如果你不这样做,你的程序将无法编译。这称为已检查异常(除非是或者扩展RuntimeException或Error,否则任何异常都是已检查的异常。)

如果方法中有任何抛出异常的内容,它将无法编译,除非您捕获异常或在方法上声明它,然后调用该方法的任何内容都必须以相同的方式处理异常。 / p>

答案 2 :(得分:3)

要回答您的具体问题,您几乎从不想说throws Exception本身。

throws子句通知用户此方法存在他们必须处理的异常情况。例如,您可能会因使用文件操作方法而导致IOException(例如,无法打开相关文件)。如果您尚未在本地处理,则需要将您的方法throws声明回调用者。

现代IDE会通知您,对于已检查的异常,您需要在使用方法时处理它们,或者将它们从调用树中的方法中抛出(通过throws子句)。

答案 3 :(得分:1)

如果抛出的异常是经过检查的异常,则必须编写它,这意味着调用者明确负责捕获或重新抛出异常。

答案 4 :(得分:1)

如果在代码中捕获异常,则不必抛出异常。如果你没有捕获它,它会被传递给调用者,这就是你需要throws子句的原因。

答案 5 :(得分:1)

.net中不存在已检查与未检查异常的概念。 原始Java大师的intention是,如果你必须声明你抛出的已检查异常,那么调用者将知道他/她必须捕获它们。例如,如果您正在处理IO库,则强制您捕获IOException。

try {
    file.delete();
} catch (IOException x) {
    // do something
}

不幸的是,在Java中过度使用了已检查的异常(请参阅spring philosophy)。关于滥用已检查异常以及它们如何污染代码存在很多批评。抛出检查异常的库通常会导致用户编写如下代码:

try {
    file.delete();
} catch (IOException e) {
   throw new RuntimeException(e);
}

如果您正在编写图书馆,请考虑您所检查的例外是否会阻碍/骚扰用户,以及他/她是否必须抓住他们。

关于这个问题有不同的思想流派,但今天势不可挡的趋势是避免检查异常(参见spring,hibernate,apache-commons等成功项目)。

我可以证明,今天我不再抛出已检查的例外情况。如果用户应该知道异常非常重要,那么在javadocs中记录好它,但是让用户可以自由编写更清晰的代码。

编辑:我发现了一个类似的问题(以及我以前的一个答案)here。也许它会有所帮助。

答案 6 :(得分:0)

在C ++中(我不能用C#但它可能类似)关键字throw是对所有异常类型的限制,所以如果没有关于抛出异常的规范,你可以假设它可以是任何东西。< / p>

在Java中,您可以假设如果没有使用关键字throws,则此方法不会抛出任何人。 (你可以肯定,但不需要运行时异常)。因此,如果有一些关于投掷的规范,你必须抓住它传播它

答案 7 :(得分:0)

如果异常可能无法在当前方法中处理并且可以将其传播到该方法的调用方,则使用

“throws”关键字。

调用者可以使用“throws”关键字处理该异常或将该异常传播到另一个方法。

Exception类是Runtime Exception的基类。

答案 8 :(得分:0)

回答主题而不是说明:Class不能使用“throws”关键字。只有方法和构造函数可以。

如果没有hack,你可以在初始化块上使用throws(但不是静态)。你可以在构造函数上设置throws然后它将编译。

public class Example{ // here you can not use throws
{
    BufferedReader in = new BufferedReader(new FileReader("asdf"));   
}   
public AbstractWithConstantsOnly() throws FileNotFoundException {   }

public static void main(String[] args) throws Exception {
    new Example();
}
}