两个最流行的面向对象框架(Java 和 .NET)中的异常处理设计基于这样一个概念,即是否处理特定异常的问题应该主要取决于它的类型,以及人们将要处理的异常类型。想抓都会有等级关系。我认为 Java 和 .NET 那样做是因为 C++ 那样做,而 C++ 那样做是因为希望避免将任何非原始类型硬编码到语言中。catch
在没有可以将所有异常转换为的硬编码类型的情况下,语句不可能知道任何关于它没有明确准备的异常类型的任何信息。如果仅捕获可以解码的异常才有意义,那么catch
语句将能够明智地作用于那些类型,并且只有那些派生自语句中的类型的类型。
回想起来,最好catch
通过类层次结构以外的其他方式来决定应该对哪些异常采取行动和/或通过特定语句解决哪些异常。除此之外,一次尝试调用方法可能会因为多个问题而失败;如果发生这种情况,与这些问题中的任何catch
一个相关联的每一个都应该触发,但只有当所有问题都得到解决后,才能恢复正常执行。不幸的是,Java 和 .NET 都没有任何机制来实现这种行为。
关于层次结构的顶层布局,我认为有一个假设,即方法可能抛出的每一种异常要么总是被直接调用代码预期,要么永远不会被任何调用代码预期。后一种类型的例外被归类为Error
或RuntimeException
,而前一种类型的例外被放在别处。在实践中,方法调用者是否期望异常的问题应该与它在层次结构中的位置甚至异常类型无关。方法被声明为的事实throws FooException
并不意味着调用代码总是期望异常可能发生。代码调用一个声明为抛出异常的方法是很常见的,但认为调用周围的环境使得在实践中特定调用永远不会抛出。如果确实发生异常,它应该表现得像意外异常,即使外部执行上下文期望捕获该类型的异常。不幸的是,异常处理机制就是这样,我不希望有任何大修。