异常处理
异常机制:用于保障我们的程序更加健壮
异常的处理流程:
①当执行try块时引发了异常。系统【会自动生成】一个异常对象
②【依次】用异常对象 instanceof catch块异常类。
③如果instanceof运算返回true,系统会自动将异常对象传给catch块后的形参,并执行catch块中的代码。
不同的catch块负责对不同的异常进行处理。
对于一个异常,最多只有一个catch块能捕捉到该异常。
多个catch块捕捉异常时,先捕捉子类的异常,再捕捉父类的异常
注意:①捕捉多种类型的异常时,多种异常类型之间要用竖线(|)隔开。
②捕捉多种类型的异常时,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值。
★ java7开始,一个catch块可以捕捉多种类型的异常。
catch(异常类1 | 异常类2 | 异常类3 . . . ex)
访问异常对象:
当catch块捕捉到异常时,异常对象会作为catch块的参数被传入。
因此在catch块可以通过该参数来访问实际的异常对象。
- getMessage():返回异常的信息。
- printStackTrace():输出异常的跟踪栈(堆栈)信息。
==============================================================
程序排错的方法:
排错时,应该从异常发生的第一个你自己开发的程序位置找起。
==============================================================
异常处理的完整语法格式:
try
{
//正常业务处理
}
catch(异常 ex) 【0~N个】
{
//进行异常处理
}
finally 【0~1个】
{
}
try不能单独存在,catch块和finally块至少要有一个陪它一起存在。
finally - - - 通常用于资源回收。JVM会保证【finally块总是得到执行】。return语句也不行。
无论程序是否抛出异常,甚至程序遇到return语句----都不能阻止finally的执行。、
除非遇到退出虚拟机的代码,才能阻止finally的执行。
JDK1.7自动关闭资源的try语句
try(//在该圆括号里打开的资源,JVM可以自动关闭)
{
//代码块
}
【备注:】自动关闭的try语句,相当于在最后有一个隐藏的finally语句。
对于自动关闭资源的try语句,可以没有catch和finally语句----可以孤独的存在。
自动关闭资源的try语句,有三个注意点:
①只有放在try后面的圆括号里的资源才会被关闭。
②能被自动关闭的资源必须实现Closeable接口或者AutoCloseable接口
③try后面的圆括号里只能声明、并创建可自动关闭的资源。
异常的分类
Checked异常、Runtime异常
Checked异常
概念:不是RuntimeException子类的异常,都是Checked异常。
Checked异常----没有完善的错误处理的代码,不会得到执行的机会。
----编译器会强制检查;编译器要求程序员:①要么处理该异常 ②要么声明抛出该异常
用throws声明抛出异常
----该方法已经注意到了这些异常,但目前该方法无法、不想处理该异常
方法重写:两同,两小,一大
子类方法声明抛出的异常类型应该是父类声明抛出异常类型的子类或相同。
【注意:】子类方法声明不抛出异常,也是可以的。
Runtime异常
概念:RuntimeException子类的异常,都是Runtime异常。
Runtime异常----程序员想捕捉就捕捉;如果现在不想处理,编译器不会强制检查。
有名的Runtime异常:
- NullPointerException(空指针异常)
- ArrayIndexOutOfBoundsException(数组下标越界异常)
- ClassCastException(类型转换异常)
- ArithmethicException(算数异常)
- NumberFormatException(数字格式异常)
- illegalArgumentException(非法数据异常)
throw抛出异常
异常,其实很主观
—— 只要程序出现与我们业务不相关的情况,就可认为是异常
对于业务相关的异常,必须由程序员通过代码来抛出,这样就要用throw了。
throws与throw的区别
①throws只能在方法签名中使用。
throws后可以紧跟【多个】异常类的【类名】,多个类名之间用逗号隔开。
②throw就是一条普通语句。
throw后紧跟【一个】异常【实例】。
抛出异常可能有两种:
①程序不能成功的执行完成,由系统自动生成异常对象,并抛出
②程序出现了与业务规则不符的情况,由程序员来创建异常对象,并通过throw关键字抛出。
catch可以与throw结合使用
有一种场景:A方法调用了B方法,当B方法出现了异常,而且B方法自己捕捉了异常。此时,A方法就不知道B方法曾经发生了异常。
但在有些时候,虽然B自己捕捉了异常,但A依然需要知道被调用的方法曾经发生的异常
此时的做法,可以是先用catch来捕捉原有的异常,再用throw抛出一个自定义的异常
【异常的转译】