发现错误的理想时机是在编译阶段,即在程序运行之前,而这往往是不现实的——编译器只能发现代码中的语法错误。在运行阶段,因输入数据、对象当前状态以及所处的运行环境等方面的差异,程序可能会出现各种各样的运行时错误,如除数为0、要读写的文件不存在、数组下标越界等。
Java的异常与错误处理机制提供了一种在不增加控制流程代码的前提下检查和处理错误的能力,使得编写错误处理的代码变得可控。
1、异常的概念
Java中的异常是指Java程序在运行时可能出现的错误或非正常情况,至于是否出现,通常取决于程序的输入、程序中对象的当前状态以及程序所处的运行环境。
2、异常的分类
JDK类库中提供了数十个类用以表示各种各样具体的异常,其继承关系如下图:
- Throwbale:Java中的异常被描述为“可抛出”的事物,它是所有异常类的父类。Throwable有两个子类Error(错误)和Exception(异常)。
- Error:描述了JRE的内部错误、资源耗尽等情形,一般由Java虚拟机抛出。Error异常出现时,程序是没有能力处理的,因此不应编写代码处理Error及其子类异常。
- Exception:是开发者能够通过编写代码直接处理和控制的异常。若无特别说明,异常一般是指Exception及其子类所代表的异常。程序若出现Exception及其子类异常(不包括RuntimeException及其子类),则必须编写代码进行处理,否则视为语法错误。相对于Error,开发者应该更关注此种异常。
- RuntimeException:继承自Exception,代表“运行时”异常。此种异常出现的频率一般比较高(或者说验证程度较Exception低),所以程序处不处理RuntimeException及其子类异常均可。
3、异常处理及语法
3.1、throw语句以及throws语句
throw语句
throw语句的语法较为简单——在throw语句后面跟上要抛出的异常的对象即可。
throw 异常对象;
说明:
- 一条throw语句只能抛出一个异常对象
- 与return语句类似,throw语句也会改变程序的执行流程。一般来说,执行完throw语句后,会结束所在方法的执行。
- throw语句必须是某个语法结构的最后一条语句
throws语句
若方法中含有throw语句,并且抛出的是Checked型异常,则该方法的声明部分必须加上throws子句——告知JRE该方法可能会抛出某些异常。
public void doSomething() throws IOException, ArithmeticExcepyion {
//方法体
}
说明:
- 关键字throws后可以跟多个异常,彼此用逗号分开,且没有先后顺序之分。
- 关键字throws后可以跟方法体中并未抛出的异常。
- 关键字throws后可以同时出现Unchecked和Checked型异常
- 若方法体会抛出Unchecked型异常,则这些异常出不出现在throws子句中均可
- 若方法体会抛出Checked型异常,并且未编写代码处理这些异常,则该方法的throws子句中必须包含这些异常
- 若父类的某个方法待throws子句(设抛出的异常为E)则子类在重写该方法时,要么声明抛出E或E的子类,要么不含throws子句,否则会有语法错误。
3.1、try-catch
try-catch语句用于捕获和处理异常——讲那些可能抛出异常的代码放在try结构中,并在catch结果中捕获和处理相应的异常,格式如下:
try{
//可能抛出异常的代码
}catch(SomeException e){
// 处理SomeException 异常的代码
}catch(AnotherException e){
//处理AnotherException 异常的代码
}