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

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

public void Test() throws Exception 

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

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

回答你的两个具体问题:

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

Java课程的例外章节非常擅长详细解释这一点, JavaWorld有一篇关于抛出和捕获exception的好文章 ,我总是发现它是传递给人们的好参考。

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

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

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

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

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

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

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

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

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

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

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

如果您正在编写库,请考虑您检查的exception是否会阻碍/骚扰用户,以及他/她是否必须抓住它们。

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

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

编辑:我在这里找到了一个类似的问题(以及我以前的一个答案)。 也许它会有所帮助。

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

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

如果exception可能无法在当前方法中处理并且它可以传播到该方法的调用者,则使用“throws”关键字。

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

Exception类是Runtime Exception的基类。

回答更多主题而不是描述 :类不能使用“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(); } }