10.4.4 Java 7增强的throw语句

10.4.4 Java 7增强的throw语句

对于如下代码:

1
2
3
4
5
6
7
8
9
try
{
new FileOutputStream("a.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
throw ex; // ①
}

上面代码片段中的①号代码再次抛出了捕获到的异常,但这个ex对象的情况比较特殊:
程序捕获该异常时,声明该异常的类型为Exception;
但实际上try块中只调用了FileOutputStream构造器,这个构造器声明只是抛出了FileNotFoundException异常。
Java 7以前,Java编译器的处理”简单而粗暴”——由于在捕获该异常时声明ex的类型是Exception,因此Java编译器认为这段代码可能抛出Exception异常,所以包含这段代码的方法通常需要声明抛出Exception异常。例如如下main方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;

public class ThrowTest2
{
public static void main(String[] args)
// Java 6认为①号代码可能抛出Exception,
// 所以此处声明抛出Exception
throws Exception
{
try
{
new FileOutputStream("a.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
throw ex; // ①
}
}
}

Java 7开始,Java编译器会执行更细致的检查,Java编译器会检查throw语句抛出异常的实际类型,这样编译器知道①号代码处实际上只可能抛出FileNotFoundException异常,因此在调用者main方法签名中只要声明抛出FileNotFoundException异常即可。即可以将代码改为如下形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;

public class ThrowTest2
{
public static void main(String[] args)
// Java 7会检查①号代码可能抛出异常的实际类型,
// 因此此处只需声明抛出FileNotFoundException即可。
throws FileNotFoundException
{
try
{
new FileOutputStream("a.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
throw ex; // ①
}
}
}

总结

Java 7开始,Java编译器会检查throw语句抛出异常的实际类型,而不是直接使用catch块括号中声明异常形参的异常类型