读完第九章违例控制以后并没有太大的感想,主要是因为程序写的并不多而且都比较简单,所以并没有体验到违例控制带来的好处,虽然书中一直强调它的重要,但是不实际体验到估计很难有感想。嘛,不过对于书中提到的一些问题我还是仔细考虑并进行了测试的。
第一,关于finally块中代码调用的时机
关于这个问题讨论的代码如下:
- class Ex extends Exception {}
- public class AlwaysFinally
- {
- public static void main(String[] args)
- {
- System.out.println("Entering first try block");
- try
- {
- System.out.println("Entering second try block");
- try
- {
- throw new Ex();
- }
- finally
- {
- System.out.println("finally in 2nd try block");
- }
- }
- catch(Ex e)
- {
- System.out.println("Caught Ex in first try block");
- }
- finally
- {
- System.out.println("finally in 1st try block");
- }
- }
- }
输出结果如下:
Entering first try block
Entering second try block
finally in 2nd try block
Caught Ex in first try block
finally in 1st try block
该代码13行抛出了一个违例,正常来说此时应该立刻查找对应catch违例控制器并跳转,如果该层中没有找到对应违例代码就转向更高级的一层中查找。但是finally in 2nd try block却在Caught Ex in first try block之前得到了输出,但是Caught Ex in first try block又在finally in 1st try block之前得到输出,可见,如果违例不能在当前一层的catch中捕获的话,那么跳转到更高一级之前必须先把finally块中的代码执行了,然后再跳到更高一层去搜索违例控制器。
第二,关于书中提到的违例丢失的问题
编译执行如下代码:
class VeryImportantException extends Exception {
public String toString() {
return "A very important exception!";
}
}
class HoHumException extends Exception {
public String toString() {
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantException {
throw new VeryImportantException();
}
void dispose() throws HoHumException {
throw new HoHumException();
}
public static void main(String[] args) throws Exception {
LostMessage lm = new LostMessage();
try
{
try
{
lm.f();
}
finally
{
lm.dispose();
}
}
catch(VeryImportantException e)
{
System.out.println("VeryImportantException Catch");
}
catch(HoHumException e)
{
System.out.println("HoHumException Catch");
}
}
}
其结果为:
HoHumException Catch
可以看出VeryImportantException完全被丢失了。书中对于这个问题评论为“这是一项相当严重的缺陷,因为它意味着一个违例可能完全丢失。而且就象前例演示的那样,这种丢失显得非常“自然”,很难被人查出蛛丝马迹。而与此相反,C++里如果第二个违例在第一个违例得到控制前产生,就会被当作一个严重的编程错误处理。或许Java 以后的版本会纠正这个问题。”书中使用的java版本为java1.1。但是上述程序是在java1.6环境下执行的。可见这个这个问题并没有得到解决。所以以后再使用这种结构的违例控制时,必须注意不要在finally块中编写 可能会导致当前违例丢失的代码。