在下面的源代码中,我重新抛出Exception
为什么没有必要在方法的签名上放置throws
关键字?
public void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
} catch (Exception e) {
throw e;
}
}
答案 0 :(得分:29)
此行为似乎仅在Java 1.7上发生。使用1.6进行编译时,我收到以下编译器错误消息:
c:\dev\src\misc>javac -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
Main.java:22: error: unreported exception Exception; must be caught or declared
to be thrown
throw e;
^
1 error
1 warning
但是使用Java 1.7,它会编译。
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
...直到我实际在Exception
块中抛出try
:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new IOException("Fake!");
} catch (Exception e) {
throw e;
}
...编译
c:\dev\src\misc>javac -source 1.7 Main.java
Main.java:22: error: unreported exception IOException; must be caught or declare
d to be thrown
throw e;
^
1 error
看起来Java 1.7足够智能,可以通过分析Exception
块代码来检测可能抛出的try
(s)类型,其中1.6只看到了throw e;
键入Exception
并仅为此提供错误。
将其更改为抛出RuntimeException
使其按预期编译,因为一如既往,未经检查的Exception
不需要throws
子句:
public static void throwsOrNotThrowsThatsTheQuestion() {
try {
// Any processing
throw new RuntimeException("Fake!");
} catch (Exception e) {
throw e;
}
...编译
c:\dev\src\misc>javac -source 1.7 Main.java
c:\dev\src\misc>
解释
这是发生了什么:
Java 7引入了more inclusive type checking。引用...
考虑以下示例:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws Exception {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
}
此示例的try块可能抛出FirstException或SecondException。假设您要在rethrowException方法声明的throws子句中指定这些异常类型。在Java SE 7之前的版本中,您不能这样做。因为catch子句的异常参数e是类型Exception,并且catch块重新抛出异常参数e,所以只能在rethrowException方法声明的throws子句中指定异常类型Exception。
但是,在Java SE 7中,可以在rethrowException方法声明中的throws子句中指定异常类型FirstException和SecondException。 Java SE 7编译器可以确定语句throw e抛出的异常必须来自try块,并且try块抛出的唯一异常可以是FirstException和SecondException。即使catch子句的异常参数e是类型Exception,编译器也可以确定它是FirstException或SecondException的实例:
(强调我的)
public void rethrowException(String exceptionName)
throws FirstException, SecondException {
try {
// ...
}
catch (Exception e) {
throw e;
}
}
答案 1 :(得分:6)
java.lang.Exception是一个经过检查的异常,因此无法工作甚至编译。它可以使用unckeched(java.lang.RuntimeException)。 无论你是否在catch块中抛出异常,绝对没有区别。
编译器错误看起来像这样(取决于编译器):
java:未报告的异常java.lang.Exception;必须被抓住或宣布被抛出
编辑:如果你从未真正抛出异常,Java 7可以处理这种情况
答案 2 :(得分:3)
如果您检查了已检查的异常,则需要将其放在抛出列表中
public void retrhowChecked() throws Exception {
try {
throw new IOException();
} catch(Exception e) {
throw e;
}
}
如果你抛出一个未经检查的异常,你不需要将它放在throws列表中,你可以使用它来在未经检查的异常中包装一个已检查的Exception,以避免在你更改有问题的方法时破坏使用此方法的代码以这种方式,它在更改后可能会产生一个检查异常。但你必须小心,检查Exception是否有待处理!
public void retrhowUnchecked() {
try {
throw new IOException();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
详细了解例外情况here。
答案 3 :(得分:3)
为什么没有必要将throws关键字放在方法的上面 签名σ
您可以将// Any processing
放弃任何已检查的例外。
示例:
编译正常。
public void throwsOrNotThrowsThatsTheQuestion() {
try {
throw new RuntimeException();
} catch (Exception e) {
throw e;
}
这将无法编译,您需要添加throws
子句。
public void throwsOrNotThrowsThatsTheQuestion() {
try {
throw new Exception();
} catch (Exception e) {
//do something like log and rethrow
throw e;
}
}
这是自java 7以来的工作。在以前的版本中引发了异常。更多信息rethrow in java 7
答案 4 :(得分:0)
当你对方法使用throws时,这意味着调用该方法的语句必须用try catch块包围。
但是如果该方法已经包含了try catch块,则不需要使用thorws声明,因为该方法抛出的异常仅在那里处理。
调用此方法的语句不需要用try catch块包围。
希望这可以解除你的怀疑。
答案 5 :(得分:0)
抛出新的
Exception();
是你永远不应该做的事情 阻止,但您可能必须或想要执行throw new SomeException(throwable);
(保留完整堆栈跟踪) 抛出throwable;
以符合您方法的API, 例如当它声明抛出SomeException
但你正在调用代码时 可能会抛出您不想添加的IOException
方法的抛出条款。可能最常见的情况是新的RuntimeException(throwable);至 避免完全抛出投掷条款。