在捕获异常的地方存在歧义

时间:2011-05-02 09:00:03

标签: java exception-handling try-catch

在下面的代码中,将捕获抛出的异常?

public interface MyInterface {
    public void execute() throws Exception;
}

public class MyImplementor implements MyInterface {
    public void execute() throws Exception {
        throw new MyException();
    }
}

public class MyMainClass {
    public static void main(String args[]) {
        try {
            MyImplementor temp = new MyImplementor();
            temp.execute();
        } catch(MyException e) {
            sysout("MyException");
        } catch(Exception e) {
            sysout("Exception");
        }
    }
}

MyException是一个扩展Exception

的类

那么这个异常在哪里被抓住了?此外,编译器使用什么逻辑来决定它被捕获的位置?

如果我放置了

catch(Exception e)

之前的

catch(IOException e)

会改变控制流吗?

5 个答案:

答案 0 :(得分:5)

  

那么这个异常在哪里被抓住了?

在第一个处理程序中。

  

此外,编译器使用什么逻辑来决定它被捕获的位置?

编译器不是“决定”......

行为由Java语言规范section 11.3指定:

  

“抛出异常时,控制从导致异常的代码转移到处理异常的try语句(§14.20)最近动态封闭的catch子句“。

(强调补充。)

换句话说,将传播的异常(使用等效的instanceof)与每个处理程序的异常类型进行比较,按处理程序的声明顺序进行比较。执行匹配异常的第一个。

  

如果我在“catch(Exception e)”之前放置“catch(IOException e)”会改变控制流吗?

是。 (假设您的意思是MyException而不是IOException。)这是上述行为的直接逻辑结果。


这意味着您应首先使用处理程序为最具体的异常排序处理程序。如果你弄错了,一些Java编译器和代码质量/错误检测器工具会发出警告,但这不是编译错误。

答案 1 :(得分:3)

它的一些类似于if...else if。如果满足一个条件,它将从剩余条件中退出...如果出现异常,catch(Exception e)满足所有类型的异常,因为它是所有例外的父母。所以异常是在顶层本身捕获的。编译器不允许这样做。因此,请根据从底部到顶部的继承顺序放置catch。然后只有你可以根据其类型获得异常。

答案 2 :(得分:2)

你不能那样做。 (checked-)异常的顺序是根据继承顺序。 您不能在从此父级继承的异常之前添加父异常。 IDE抱怨并且代码不会被编译!

在您的情况下,如果您的代码抛出IOException,它将在IOException catch块中捕获,然后才会到达Exception catch块。在其他情况下,Exception-catch块将捕获任何其他异常

答案 3 :(得分:1)

a)你不能颠倒catch块的顺序。如果你这样做了,IOException的块将变得无法访问 - IOException的一个实例也是Exception的一个实例,因此catch (Exception e)块会捕获它并且你永远不会遇到catch (IOException e)块。然后代码将无法编译 - 不允许无法访问的代码。

b)由于MyException扩展了Exception而不是IOException,因此catch (IOException e)块不会捕获它。因此它将被catch (Exception e)块捕获。

更新

您现在已经改变了问题,所以答案略有不同:

a)你仍然无法扭转这些障碍。

b)现在您已将第一个块更改为catch (MyException e),抛出的异常将被捕获。程序是,编译器查看每个catch块。如果它试图处理的异常是被捕获的异常的实例,则执行该catch块。如果没有,它将进入下一个catch块。如果没有更多的catch块,则会突然终止执行(来自Java语言规范的术语)。

答案 4 :(得分:1)

在您的代码中,未定义MyException,但它应该扩展Exception或RuntimeException。 无论如何它都没有任何区别,你的程序将打印“MyException”,因为它是抛出的异常类型。