Java程序设计(高级及专题)- 异常机制

==================================================================

异常处理的5个关键字:try、catch、throw、throws和finally。关于它们的用法和注意点,会在下面一一介绍。

Java的异常处理模型基于三种操作: 声明异常、抛出一个异常和捕获一个异常。

  • 声明异常(throws)

//不捕获,而是声明该异常,交给调用者处理

public static void method() {

/try-catch块捕获异常/

if(5 > 3) {

try {

throw new Exception(); //抛出异常

} catch (Exception e) {

e.printStackTrace();//捕获异常后的处理

}

}

}

在Java中,当前执行的语句必属于某个方法,Java解释器调用main方法执行开始执行程序。若方法中存在检查异常,如果不对其捕获,那必须在方法头中显式声明该异常,以便于告知方法调用者此方法有异常,需要进行处理。 在方法中声明一个异常,方法头中使用关键字throws,后面接上要声明的异常。若声明多个异常,则使用逗号分割。

例如:

public static void method() throws IOException, FileNotFoundException{

//something statements

}

【注意】若是父类的方法没有声明异常,则子类继承方法后,也不能声明异常。

  • 抛出异常(throw)

如果代码可能会引发某种错误,可以创建一个合适的异常类实例并抛出它,这就是抛出异常。

例如:

public static double method(int value) {

if(value == 0) {

throw new ArithmeticException(“参数不能为0”); //抛出一个运行时异常

}

return 5.0 / value;

}

大部分情况下都不需要手动抛出异常,因为Java的大部分方法要么已经处理异常,要么已声明异常。所以一般都是捕获异常或者再往上抛。

  • 捕获异常(try-catch)

当抛出一个异常时,可以在try-catch块中捕获它并进行处理。

try {

//包含可能会出现异常的代码以及声明异常的方法

} catch (ClassCastException e) {

//捕获指定异常并进行处理

}catch(Exception ex) {

//捕获指定异常并进行处理

}

若执行try块的过程中没有发生异常,则跳过catch子句。若是出现异常,try块中剩余语句不再执行。开始逐步检查catch块,判断catch块的异常类实例是否是捕获的异常类型。匹配后执行相应的catch块中的代码。如果异常没有在当前的方法中被捕获,就会被传递给该方法的调用者。这个过程一直重复,直到异常被捕获或被传给main方法(交给JVM来捕获)。

  • catch捕获异常的顺序

一个通用父类可以派生出各种异常类,如果一个catch块可以捕获一个父类的异常对象,它就能捕获那个父类的所有子类的异常对象。如果捕获的是多个同类型异常,则子类异常在前,父类异常在后,不然会导致编译错误。这是因为父类异常囊括了子类异常,如果父类异常在前,子类异常永远捕获不到,导致有时候无法准确描述错误信息。

try {

File f =new File(“C:\ProgramFile\test.txt”);

FileInputStream fis = new FileInputStream(f);

} catch (FileNotFoundException e) { //子类异常

e.printStackTrace();

} catch(IOException ie) { //父类异常

ie.printStackTrace();

} catch(Exception e) { //基类运行时异常

e.printStackTrace();

}

这里只是用于演示catch块捕获的顺序。捕获多个异常时,可以使用catch(Exception1 | Exception2| Exception3)的形式来优化捕获异常的代码结构。

将声明异常、抛出异常和捕获异常综合在一起。

例如:

public static void main(String[] args) {

for(int i = 2; i < 100; i++) {

//对运行时异常,可以选择捕获也可以不选择捕获

if(isPrime(i)) {

System.out.print(i + " ");

}

}

} //检测是否为质数

public static boolean isPrime(int num) throws IllegalArgumentException{

//抛出一个运行时异常

if(num < 2) throw new IllegalArgumentException(“质数不能小于2”);

for(int i = 2; i < num; i++) {

if(num % i == 0) {//若能被1和本身之外的数整除,则非质数

return false;

}

}

return true;

}

因为抛出的是运行时异常,可以选择捕获或者不捕获。但如果抛出检查异常,在编译时就必须选择捕获或者声明。

  • finally语句块

无论是否有异常,finally块中的代码总是会被执行的。 finally语句在执行关闭资源的语句时非常有用。

//第一种形式 式

try {

//执行程序代码,可能会出现异常

}catch(Exception e) {

//捕获异常并处理

}finally {

//必执行的代码

}

//第二种形

try {

//执行程序代码,可能会出现异常

}finally {

//必执行的代码

}

  • try-catch-finally的执行流程

try块中引起异常,异常代码之后的语句不再执行,若被catch块捕获,执行匹配的catch块,然后执行finally语句。若catch块不能捕获异常,则执行finally语句,之后将异常传递给这个方法的调用者。

Scanner sc = new Scanner(System.in);

int a = 0; //保证局部变量a在各个块中可用

try {

a = sc.nextInt();

if(a < 0) throw new IllegalArgumentException();

System.out.println(“执行完try语句。a:” + a);

}catch(IllegalArgumentException e){

System.out.println(“执行catch语句”);

System.out.println(“数值小于0,不符合。已设为默认值 1”);

a = 1;

}finally {

System.out.println(“执行finally语句。a:” + a);

}

输出并分析:

//未引发异常 //引发异常并捕获

5 -5

执行完try语句。a:5 执行catch语句

执行finally语句。a:5 数值小于0,不符合。已设为默认值 1

执行finally语句。a:1

  • try-finally的执行流程

try块中引起异常,异常代码之后的语句不再执行,直接执行finally语句。 try块没有引发异常,则执行完try块就执行finally语句。

try-finally可用在不需要捕获异常的代码,可以保证资源在使用后被关闭。例如IO流中执行完相应操作后,关闭相应资源;使用Lock对象保证线程同步,通过finally可以保证锁会被释放;数据库连接代码时,关闭连接操作等等。

例如:

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值