1. 异常的概念
异常是指程序运行过程中发生的一些不正常事件(如除0溢出,数组下标越界,所要读取的文件不存在)
抛出异常:Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该对象封装了异常事件的信息,并将其提交给Java运行系统,这个过程称为抛出异常,不处理的话会直接导致程序中断。
设计良好的程序应该在程序异常发生时提供处理这些异常的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。
2. 异常的分类
-
Error是无法处理的异常,比如OutOfMemoryError,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常。
-
Exception,也就是我们经常见到的一些异常情况,这些异常是我们可以处理的异常,是所有异常类的父类。
-
unchecked exception(非受查异常),包括Error和RuntimeException,比如常见的NullPointerException、IndexOutOfBoundsException。对于RuntimeException,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。
-
checked exception(受查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常),由代码能力之外的因素导致的运行时错误。java编译器强制程序员必须进行捕获处理,比如常见的有IOExeption和SQLException。如果不进行捕获或者抛出声明处理,编译都不会通过。
-
典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。
-
典型的非RuntimeException包括IOException、SQLException等。
3. 异常的处理机制
捕获机制:try-catch-finally
-
try{}语句块:里面是要检测的Java代码,可能会抛出异常,也可能会正常运行
-
catch(异常类型){}块:是当Java运行时,系统接收到try块中所抛出异常对象时,会寻找能处理这一异常catch块来进行处理,注意异常类型需要与try{}语句块可能抛出的异常要匹配。可以有多个catch块。不同的异常类型对应不同的处理代码。
-
finally{}语句块:不管系统有没有抛出异常,都会去执行,一般用来释放资源。除了在之前执行了System.exit(0)
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExceptionDemo1 {
public static void main(String[] args) {
System.out.println("Please input a num");
Scanner scan=new Scanner(System.in);
int res=0;
try{
//System.exit(0); 执行这句代码finally语句块内容将不会被执行
int num=scan.nextInt();
res=10/num;
//键盘输入的数据类型不匹配时抛出的异常
}catch(InputMismatchException e){
System.out.println(e.getMessage()); //e.printStackTrace();
//除数为0时抛出的数学异常
}catch(ArithmeticException e){
System.out.println(e.getMessage());
//把确定可能抛出的异常类放在基类Exception前面。用基类Exception捕获未知的异常
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
//Finally代码块无论如何都会执行,除非try块中有System.exit(0);
//释放资源,比如关闭打开的文件,删除一些临时文件等
System.out.println("result: "+res);
}
}
}
抛出的异常交给调用方法的人来捕获:异常处理和异常清理的解耦。——throw,throws
public static void testTryFinally(String name){
try{
System.out.println(name.length());
}finally{
System.out.println("end");
}
}
抛出:throw,throws
- throw:手动抛出异常,一般由程序员在方法内抛出Exception的子类异常。
- throws:声明在方法名之后,告诉调用者,该方法可能会抛出异常,也就是说异常发生后会抛给调用者,由调用者处理异常。
public class ExceptionDemo2 {
public static void main(String[] args) {
Bar bar=new Bar();
try{
bar.Enter(15);
}catch(IllegalArgumentException e){
//调用者在这里捕获bar.Enter()方法的非受查异常。
System.out.println("错误信息: "+e.getMessage());
}
//如果没有上面的catch语句块,程序会中断,这一句就不会执行
System.out.println("end");
}
}
class Bar{
//throws标注在方法名之后,提示调用者,可能抛出的异常,让调用者不要忘记捕获
public void Enter(int age) throws IllegalArgumentException {
if(age<18){
//抛出非受查异常,但是并不捕获,捕获的动作交给调用者执行
throw new IllegalArgumentException("年龄不合格");
}else{
System.out.println("欢迎光临");
}
}
}