异常,是程序在运行期间发生的意外状况。对于程序设计者需要尽可能地预见可能发生的意外,尽可能地保证程序在各种糟糕的情况下仍可以运行。Java语言提供了成熟的异常处理机制。
Java异常体系Java将所有的错误封装成为一个对象,Throwable类是这个异常体系的根,它有两个子类:Error和Exception。
ErrorError类及其子类对象代表了程序运行时Java系统内部的错误。对于Error,程序设计者无能为力,程序不能从Error恢复,因此不必处理它们,从技术上讲Error不是异常。
ExceptionException通常是由于某个资源不可用,或者正确执行程序所需的条件不满足所造成的。Exception类及其子类对象是程序设计者应该关心、并尽可能加以处理的部分。Java将Exception分为两类:
RuntimeException(运行时异常,也称为未检查异常Unchecked Exception)非RuntimeException(也称为已检查异常 checked Exception)以下称未检查异常和已检查异常
未检查异常未检查异常包含java.lang.RuntimeException类及其所有子类未检查异常是程序员没有进行必要的检查,因疏忽或者是错误而引起的异常,是可以避免的已检查异常除了java.lang.RuntimeException之外的所有异常都属于此类最常见的如IOException及其子类(像找不到文件的FileNotFoundException,意外到达文件尾部EOFException等都是它的子类)、数据库访问错误SQLException、解析时出现的异常ParseException等,已检查异常是不可避免的异常的捕获与处理try语句块将可能产生异常的代码放在try语句块中尝试执行,异常发生之后的代码不会被执行在程序执行过程中,该段代码可能会产生并抛出一种或几种异常,这些异常都由它后面的catch负责捕获、处理。所以一个try语句块后面可以跟多个catch语句块(从语法的角度也可以一个catch都没有)catch语句块每个catch语句块捕获、处理一种类型的异常。当异常发生时,程序会中断正常的流程,离开try语句块去执行相应的catch语句块。在catch中声明了异常对象(如ParseException e),异常对象封装了异常事件的相关信息,在catch语句块中可以使用这个对象获取这些信息,常用方法包括:getMessage():返回该异常的详细描述字符串。printStackTrace():将异常事件的跟踪栈信息输出。注意:一般情况下,catch语句块只能捕获一种异常,但是Java 7 SE之后,允许catch捕获多个Exception,即当出现多个异常处理措施时,可以使用 | 符号隔开跟在catch后面。但是不允许这些异常出现继承关系。
finally语句块finally语句块为可选,一旦出现,无论try语句块是否抛出异常,finally代码块都要被执行finally语句块为异常处理提供统一的善后处理,使流程转到其他部分之前,能够对程序的状态进行统一的管理通常在finally语句块中进行资源释放的工作,如关闭已打开的文件、关闭数据库连接等try-catch-finally语句的执行过程基本执行流程 try块中有return语句:
先执行try块中的代码,直到遇到return语句
计算return表达式的值(此时值会被暂存,但不会立即返回)
执行finally块中的代码
最后返回之前暂存的return值
catch块中有return语句:
如果try块抛出异常,进入匹配的catch块
执行catch块中的代码,直到遇到return语句
计算return表达式的值(暂存)
执行finally块中的代码
返回暂存的return值
实例:try中有return,finally无return代码语言:javascript复制public static int test1() {
try {
System.out.println("try block");
return 1; // 这个值会被暂存
} catch (Exception e) {
System.out.println("catch block");
return 2;
} finally {
System.out.println("finally block");
}
}
// 输出:
// try block
// finally block
// 返回: 1try和finally都有return代码语言:javascript复制public static int test2() {
try {
System.out.println("try block");
return 1; // 这个值会被丢弃
} catch (Exception e) {
System.out.println("catch block");
return 2;
} finally {
System.out.println("finally block");
return 3; // 这个值会覆盖之前的return
}
}
// 输出:
// try block
// finally block
// 返回: 3 (finally中的return会覆盖try中的return)catch中有return代码语言:javascript复制public static int test3() {
try {
System.out.println("try block");
throw new Exception();
} catch (Exception e) {
System.out.println("catch block");
return 2; // 这个值会被暂存
} finally {
System.out.println("finally block");
}
}
// 输出:
// try block
// catch block
// finally block
// 返回: 2关键规则总结 finally优先执行:无论try或catch是否有return,finally都会执行(因为try、catch中是暂存的)
返回值确定时机:
如果finally中没有return:try或catch中的return值会在执行前计算并暂存,finally执行后返回
如果finally中有return:会覆盖之前try或catch中的return值
特殊情况:
如果在finally中修改了try/catch中要返回的变量,不会影响已暂存的基本类型值
但对于引用类型,修改对象状态会影响返回的对象
使用throws抛出异常基本规则代码语言:javascript复制[访问修饰符] 返回类型 方法名(参数列表) throws 异常类型1, 异常类型2, ... {
// 方法体
}子类重写父类方法是throws的规则可以抛出与父类相同的异常可以抛出父类异常的子类可以不抛出异常经典练习:下面那个语句不能通过编译? 代码语言:javascript复制public class CC {
void doStuff() throws IOException{}
}
public class CC2 extends CC{
void doStuff() throws FileNotFoundException {}
}
public class CC3 extends CC{
void doStuff() throws Exception{}
}
public class CC4 extends CC{
void doStuff(int x) throws Exception{}
}
public class CC5 extends CC{
void doStuff(){}
}自定义异常类为该异常类取一个能标识异常状况的有意义的名字。令其继承Exception类。在异常类中至少定义两个构造方法:一个是无参的;另一个是带String参数的,将此字符串传递给父类Exception的相同构造方法。这个String将作为该异常对象的描述信息(即getMessage()方法的返回值)。