一、异常处理机制
1.在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行x/y的计算时,要检测分母为0、数据为空、输入的不是数据而是字符等问题。过多的分支会导致程序的代码加长,可读性差。因此采用异常处理机制。
2.Java异常处理:Java采用异常处理机制,将异常处理的程序代码集中到一起,与正常的程序代码分开,使得程序简洁,并易于维护。
3.Java提供的是异常处理的抓抛模型。
4.Java程序执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。
5.如果一个方法内抛出异常,该异常会被抛到调用方法中。如果异常没有在调用方法中处理,它将继续被抛给这个调用方法的调用者,这个过程将一直持续下去,直到异常被处理。这一过程称为捕获(catch)异常。
6.如果一个异常回到main()方法,并且main()也不处理,则程序运行终止。
7.程序员通常只能处理Exception,而对Error无能为力。
二、实例1.使用try-catch语句处理异常
package day16; public class Test { public static void main(String[] args){ int i = 0; try{//用try{}来扩住一段有可能出现异常的代码段 System.out.println(3/i);//被除数不能为0,由于异常,使中断,可以通过异常处理机制防止程序的中断 }catch(Exception e){//当你不知道捕获的是什么类型异常时,可以直接使用所有异常的父类Exception e.printStackTrace();//提示什么类型的异常 System.out.println(e.getMessage());//或者输出getMessage的异常类型 } System.out.println("ok"); } }
打印结果为:
实例2,异常处理是通过try-catch-finally语句实现的。
try{ ...... //可能产生异常的代码 }catch(ExceptionName1 e) { ...... //当产生ExceptionName1型异常时的处置措施 }catch(ExceptionName2 e) { ...... //当产生ExceptionName2型异常时的处置措施 }finally{ ...... //无条件执行的语句 }
package day16; public class Test { public static void main(String[] args){ String[] strs = new String[]{"a","b"}; A a = null; //try-catch是为了防止程序可能出现的异常 //在捕获异常的代码块中(指try()里面的代码),如果前面的代码块有异常了,就不会执行后面的代码块了 try{ System.out.println(strs[2]);//数组越界 System.out.println(a.i);//空指针 }catch(ArrayIndexOutOfBoundsException e1){ System.out.println(e1.getMessage()); e1.printStackTrace(); }catch(NullPointerException e2){ System.out.println(e2.getMessage()); e2.printStackTrace(); }finally{//finally可写可不写,finally是捕获异常体系中最终一段会执行的部分,在IO操作和JDBC中广泛应用 System.out.println("最终输出不受影响"); } } }
打印结果为:
三、捕获异常总结
(1)try
捕获异常的第一步是用try{...}语句块选定捕获异常的范围,将可能出现异常的代码放在try语句块中。
(2)catch(Exceptiontype e)
在catch语句块中是对异常对象进行处理的代码。每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
(3)如果明确知道产生的是何种异常,可以用该异常作为catch的参数,也可以用其父类作为catch的参数。
可以用ArithmeticException类作为参数,也可以用RuntimeException类作为参数,或者用所有异常的父类Exception作为参数。
(4)捕获异常的有关信息:
与其他方法一样,可以访问一个异常对象的成员变量或调用它的方法。
①getMessage()方法,用来得到有关异常事件的信息。
②printStackTrace()用来跟踪异常事件发生时执行堆栈的内容。
(5)finally
捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其他部分以前,能够对程序的状态作统一的管理。不论在try-catch代码块中是否发生了异常事件,finally块中的语句都会被执行。(finally语句是可选的)
三、声明抛出异常
1.声明抛出异常时Java中处理异常的第二种方式
①如果一个方法中的语句执行时可能造成某种异常,但是并不能确定如何处理这种异常,则此方法应显式的声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
②在方法声明中用 throws 子句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父类。
2.声明抛出异常举例:
public void readFile(String file) throws FileFoundException{ ... ... //读文件操作可能产生FileFoundException类型的异常 FileInputStream fis = new FileInputStream(file); ... ... }
package day16; public class Test1 { public static void main(String[] args){//可以在main方法中继续抛出异常 //main方法抛出的异常直接抛到虚拟机去了,在程序中就无法处理了 B b = new B(); try {//throws在代码中抛出的异常,在调用方法中捕获处理 b.test(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class B{ int i; public void test() throws Exception{//可以使用throws在代码这抛出异常,在调用方法中去捕获处理 B b = null; System.out.println(b.i); } }
打印结果为:
3.重写方法声明抛出异常的原则
重写方法不能抛出比被重写方法范围更大的异常类型
//重写方法不能抛出比被重写方法范围更大的异常类型 public class A{ public void methodA() throws OException{ ... ... } } public class B1 extends A{ public void methodA() throws FileNotFoundException{ ... ... } } public class B2 extends A{ public void methodA() throws Exception{//error 子类重写父类的方法时,子类不能抛出比父类方法更大的异常 ... ... } }
package day16; public class Test1 { public static void main(String[] args){//可以在main方法中继续抛出异常 //main方法抛出的异常直接抛到虚拟机去了,在程序中就无法处理了 B b = new B(); try {//throws在代码中抛出的异常,在调用方法中捕获处理 b.test(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class B{ int i; //NullPointerException的父类是Exception public void test() throws NullPointerException{//可以使用throws在代码这抛出异常,在调用方法中去捕获处理 B b = null; System.out.println(b.i); } } class C extends B{ // public void test() throws Exception{//重写方法不能抛出比被重写方法范围更大的异常类型,系统会报错 public void test() throws NullPointerException { // TODO Auto-generated method stub super.test(); } }
4.人工抛出异常
(1)Java异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可以根据需要人工创建并抛出
①首先要生成异常类对象,然后通过throws语句实现抛出操作(提交给Java运行环境)。
IOException e = new IOException(); throw e;
②可以抛出的异常必须是Throwable或者其子类的实例。
package day16; public class Test1 { public static void main(String[] args){ B b = new B(); try { b.test1(200); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class B{ int age; public void test1(int age) throws Exception{ if(age >= 0 && age <= 150){ this.age = age; System.out.println("年龄是:" + this.age); }else{ throw new Exception("年龄在0到150之间"); } } }
打印结果为:
5.创建用户自定义异常类
(1)用户自定义异常类MyException, 用于描述数据取值范围错误信息。用户自己的异常类必须继承现有的异常类。
(2)创建完成后可以使用用户自定义异常类
package day16; public class Test1 { public static void main(String[] args){ B b = new B(); try { b.test2(-100); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class B{ int age; public void test2(int age) throws MyException{ if(age >= 0 && age <= 150){ this.age = age; System.out.println("年龄是:" + this.age); }else{ throw new MyException("年龄在0到150之间"); } } } class MyException extends Exception{ public MyException(String msg){ super(msg); } }
Java提供的异常的类一般是够用的,只有特殊的情况才可能需要自己编写异常类,这种情况很少见。