为什么必须在类定义中写抛出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(); } }