import java.io.IOException;
public class Arcane1 {
public static void main(String[] args) {
try {
System.out.println("Hello world");
} catch(IOException e) {
System.out.println("I've never seen println fail!");
}
}
}
-----------结果-------------
Arcane1.java:9: exception java.io.IOException is never thrown in body of corresponding try statement
} catch(IOException e) {
^
1 error
1、语言规范中描述道:如果一个 catch 子句要捕获一个类型为 E 的被检查异常, 而其相对应的 try 子句不能抛出 E 的某种子类型的异常,那么这就是一个编译期错误。
public class Arcane2 {
public static void main(String[] args) {
try {
// If you have nothing nice to say, say nothing
} catch(Exception e) {
System.out.println("This can't happen");
}
}
}
---------结果--------
正常编译和运行
2、捕获 Exception 或 Throwble 的 catch 子句是合法的,不管与其相对应的 try 子句的内容为何。
interface Type1 {
void f() throws CloneNotSupportedException;
}
interface Type2 {
void f() throws InterruptedException;
}
interface Type3 extends Type1, Type2 {
}
public class Arcane3 implements Type3 {
public void f() {
System.out.println("Hello world");
}
public static void main(String[] args) {
Type3 t3 = new Arcane3();
t3.f();
}
}
---------结果--------
正常编译和运行
3、法 f 在 Type1 接口中声明要抛出被检查异常 CloneNotSupportedException,并且在 Type2 接口中声明要抛出被检查异常 InterruptedException。Type3 接口继承了 Type1 和 Type2,因此, 看起来在静态类型为 Type3 的对象上调用方法 f 时, 有潜在可能会抛出这些异常。一个方法必须要么捕获其方法体可以抛出的所有被检查异常, 要么声明它将抛出这些异常。Arcane3 的 main 方法在静态类型为 Type3 的对象上调用了方法 f,但它对 CloneNotSupportedException 和 InterruptedExceptioin 并没有作这些处理。那么,为什么这个程序可以编译呢?
上述分析的缺陷在于对“Type3.f 可以抛出在 Type1.f 上声明的异常和在 Type2.f 上声明的异常”所做的假设。这并不正确,因为每一个接口都限制了方法 f 可以抛出的被检查异常集合。一个方法可以抛出的被检查异常集合是它所适用的所有类型声明要抛出的被检查异常集合的交集,而不是合集。因此,静态类型为 Type3 的对象上的 f 方法根本就不能抛出任何被检查异常。因此,Arcane3可以毫无错误地通过编译,并且打印 Hello world。