1 异常概述
异常是一个在程序执行期间发生的事件,它中断了正在执行的程序的正常指令流。Java语言是一门面向对象的编程语言,因此,异常在Java中也是作为类的实例的形式出现的。当在某一方法中发生错误时,这个方法创建一个对象,并且把它传递给运行时系统。这个对象就是异常对象。通过异常处理机制,可以将非正常情况下的处理代码与程序的主逻辑分离,即在编写代码主流程的同时在其他地方处理异常。Java中已经定义了很多常见的异常类,程序员也可以自定义继承于Exception类的子类或者继承于RuntimeException类的子类。
2 异常体系
异常体系借用一个视频课程中的图片如下:
3 异常关键字throw,throws,try,catch,finally
(1)throw用于方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即终止,它后面的语句都不执行。
(2)通过throw抛出异常后,如果想在上一级代码(调用者)中来捕获并处理异常,则需要在抛出异常的方法声明上使用throws关键字指明要抛出的异常类。
(3)如果是Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译器仍能顺利通过,但在运行时会被系统抛出。
(4)如果要捕捉抛出的异常,则必须使用try-catch语句。假如没有使用throws关键字抛出,则需在throw抛出异常的本方法中捕捉异常;假如使用了throws关键字抛出,则需在调用者或者更上一级方法中捕捉异常。
(5)finally关键字代码块中的内容无论异常是否发生都一定会执行,除非在finally代码块之前调用System.exit()强制退出JVM这样的方法,或者finally代码块中发生了异常,或者所在的线程死亡,或者关闭CPU才会使finally代码块无法执行。它的作用是释放占用的资源,如关闭数据库的连接。
(6)方法中可以使用多个throw抛出多个异常对象,但一次同时只能有一个异常对象会被触发(因为程序在执行到throw语句时立即终止,它后面的语句都不执行)。方法声明中也可以使用throws抛出多个用逗号隔开的异常类。可以使用多个连续的catch代码块捕捉不同的异常对象,但需要注意的是必须将异常类的子类catch代码块放在父类catch代码块之前(因为假如异常父类catch代码块放在前面,则其他的异常子类catch代码块将永远不会被触发),否则编译器会报错。
4 异常程序示例
package captain;
//自定义异常类
class MyException extends Exception{
String message;
public MyException(String ErrorMessage){
message = ErrorMessage;
}
//重写Throwable类的getMessage方法,返回异常问题信息
public String getMessage(){
return message;
}
}
public class ExceptionDemo {
static int quotient(int x, int y)throws MyException{
if(y < 0){
throw new MyException("除数不能是负数");
}
return x/y;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int result = quotient(5,-2);
}
catch(MyException e){
//e.printStackTrace();
System.out.println(e.getMessage());
}
catch(ArithmeticException e){
System.out.println("除数不能为0");
}
//Exception异常catch代码块放在其他Exception异常子类catch代码块的后面
catch(Exception e){
System.out.println("程序发生了其他的异常");
}
}
}
5 异常注意事项及经验总结
注意事项:
(1)子类在重写父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。
(2)如果父类方法抛出了多个异常,那么子类该重写方法只能抛出父类异常的子集。
(3)如果父类方法没有抛出异常,那么子类该重写方法也绝对不能抛出异常,最多只能在该方法体内try-catch捕捉异常。
经验总结:
(1)处理运行时异常时,采用逻辑去合理规避并辅助try-catch处理。
(2)在多重catch块后面可以加一个catch(Exception e)来处理可能会被遗漏的异常。
(3)对于不确定的代码,也可以加上try-catch来处理潜在的异常。
(4)尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出。
(5)具体如何处理异常,要根据业务需要和异常类型来决定。
(6)尽量添加finally代码块去释放占用的资源。