Java中异常的限制
来源:互联网 发布:gzip linux 编辑:程序博客网 时间:2024/05/29 02:05
在Java中,发现错误的最理想时机是在编译阶段,即运行程序之前。但是,在编译期间,并不能保证所有的错误都被发现,余下的问题必须在运行期间解决。这就需要错误源能通过某种方式,把适当的信息传递给某个接收者——该接收者将知道如何正确处理这个问题。异常处理是Java中唯一正式的错误报告机制,并且通过编译器强制执行。本文略过了异常处理流程等基本知识,直接讨论Java中异常的限制。
异常的限制,这是指:当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这样的限制可以保证,当派生类对象向上转型为基类对象时,它的某个方法不会抛出基类方法未声明的异常。下面的例1演示了这种限制:
例1:
class BaseballException extends Exception {}class Foul extends BaseballException {}class Strike extends BaseballException {}abstract class Inning { public Inning() throws BaseballException {} public void event() throws BaseballException { } public abstract void atBat() throws Strike, Foul; public void walk() {} }class StormException extends Exception {}class RainedOut extends StormException {}class PopFoul extends Foul {}interface Storm { public void event() throws RainedOut; public void rainHard() throws RainedOut;}public class StormyInning extends Inning implements Storm { public StormyInning() throws RainedOut, BaseballException {} public StormyInning(String s) throws Foul, BaseballException {} //! void walk() throws PopFoul {} //Compile error public void rainHard() throws RainedOut {} public void event() {} public void atBat() throws PopFoul {} public static void main(String[] args) { try { StormyInning si = new StormyInning(); si.atBat(); } catch(PopFoul e) { System.out.println("Pop foul"); } catch(RainedOut e) { System.out.println("Rained out"); } catch(BaseballException e) { System.out.println("Generic baseball exception"); } try { Inning i = new StormyInning(); i.atBat(); } catch(Strike e) { System.out.println("Strike"); } catch(Foul e) { System.out.println("Foul"); } catch(RainedOut e) { System.out.println("Rained out"); } catch(BaseballException e) { System.out.println("Generic baseball exception"); } }}
我们可以看到,Inning类中的构造器和event()函数都声明抛出了异常,但实际上在方法体中并没有抛出,这是可行并且合理的,因为采用这种方式可以强制用户去捕获可能在覆盖后的event()方法中抛出的异常,这同样适用于抽象方法,如atBat()。
我们注意观察一下接口Storm,它定义了一个和Inning类中event()方法同名的一个方法,而且参数列表也相同,并且该方法抛出了一个在Inning类中event()方法没有抛出的异常RainOut,那么如果StormyInning既继承了Inning类,又实现了Storm接口,这两个event()方法是不能互相改变彼此的异常接口的。换句话说,StormyInning中的event()方法不能声明抛出Inning类和Storm接口中event()方法声明的任何异常。
但是,这种异常限制却对构造器不起作用。你可以发现,StormyInning类的构造器中声明抛出了Inning类构造器没有抛出的异常。但是,由于在创建子类对象时会自动调用基类的构造器,所以子类的构造器的异常声明必须包含基类构造器的异常声明。同时我们可以证明,派生类的构造器不能捕获它的基类构造器所抛出的异常,因为在派生类构造器中,super()函数的调用必须放在第一行,这便不能将try-catch语句插入。
在StormyInning中,walk()函数不能通过编译,这是因为它声明抛出了在Inning.walk()中没有声明抛出的异常。如果编译器允许这么做的话,那么我们在调用Inning.walk()的时候不用做异常处理,但是在我们执行向上转型Inning inning = new StormyInning()后,再调用inning.walk()时,这个方法便可能抛出异常,但我们却并没有捕获。
覆盖后的event()方法并没有声明抛出任何异常,这说明派生类中的方法可以不声明抛出异常。这样做是可行的,因为这并不会出现上一段所描述的情况。类似的情况出现在StormyInning.atBat()上,它抛出了异常PopFoul,而Inning.atBat()抛出了异常Foul,这么做可行是因为,PopFoul是Foul的子类,能捕获Foul异常的异常处理程序肯定也能捕获到PopFoul异常。
最后我们注意到main(),如果我们使用的是StormyInning对象的话,那么编译器只会强制要求你捕获StormyInning类所抛出的异常。但是如果我们使用的是通过向上转型得到的基类Inning对象时,那么编译器就会强制你捕获基类Inning所抛出的异常。所有这些限制都是为了能产生更为强壮的异常处理代码。
- Java中异常的限制
- Java异常的限制
- java方法重写时的异常限制
- Java编程思想12.9-异常的限制
- Java 异常限制
- Java中继承的限制
- 解决MVC中JSON字符长度超出限制的异常
- MVC中JSON字符长度超出限制的异常
- 从头认识java-10.7 使用异常的限制汇总
- Java中中的异常、异常的分类
- Java中常见的异常
- Java中常见的异常
- java中异常的注意?
- Java中常见的异常
- Java中常见的异常
- Java中常见的异常
- Java中常见的异常
- Java中异常的分类
- callback in js
- 找出一个字符串中重复最多的字符以及出现的次数
- SpringMVC批量插入,js点击按钮自动增加一行
- java学习日记_29:面向对象之JDK帮助文档的使用。08.06至07
- 项目小结(1)
- Java中异常的限制
- 1.2线程信息的获取和设置
- 闭门造车【NOIP2016提高A组模拟9.10】
- HDU 1015 Safecracker (dfs)
- HDU 5879 Cure
- 链表的相关函数
- 安装openstack前的准备
- c/c++ 各个类型所占的字节数
- Java编程中在子类重载方法中调用父类中该方法时,该方法包含递归时出现的调用错误