JAVA为什么需要重新抛出异,重新抛出异常:为什么方法在没有throws子句的情况下编译?...

On the source code below I'm rethrowing an Exception.

Why is it not necessary to put the throws keyword on the method's signature?

public void throwsOrNotThrowsThatsTheQuestion() {

try {

// Any processing

} catch (Exception e) {

throw e;

}

}

解决方案

This behavior appears to occur only on Java 1.7. When compiling with 1.6, I get the following compiler error message:

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

But with Java 1.7, it compiles.

c:\dev\src\misc>javac -source 1.7 Main.java

c:\dev\src\misc>

... Until I actually throw an Exception in the try block:

public static void throwsOrNotThrowsThatsTheQuestion() {

try {

// Any processing

throw new IOException("Fake!");

} catch (Exception e) {

throw e;

}

Compiling...

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

It looks like Java 1.7 got smart enough to detect the kind of Exception(s) that might be thrown by analyzing the try block code, where as 1.6 just saw throw e; of type Exception and gave an error just for that.

Changing it to throw a RuntimeException made it compile as expected, because as always, unchecked Exceptions don't need a throws clause:

public static void throwsOrNotThrowsThatsTheQuestion() {

try {

// Any processing

throw new RuntimeException("Fake!");

} catch (Exception e) {

throw e;

}

Compiling...

c:\dev\src\misc>javac -source 1.7 Main.java

c:\dev\src\misc>

The Explanation

Here's what's going on:

Java 7 introduced more inclusive type checking. Quoting...

Consider the following example:

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;

}

}

This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.

However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:

(emphasis mine)

public void rethrowException(String exceptionName)

throws FirstException, SecondException {

try {

// ...

}

catch (Exception e) {

throw e;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值