异常
异常的基本认识
概念:
异常通常是指程序在运行过程中出现的不正常的情况这些不正常的情况可以分为两类分别是Error 与Exception在java中的异常指的是Exception类,java对可能出现的异常都封装在不同的异常类中,所有这些异常类的都继承于Exception类
Exception类:其它因编程错误或偶然的外在因素导致的一般性问题,通过异常处理机制处理后程序可以正常运行的情况,例如数组越界异常,算术运算规则异常,空指针异常,类转换异常,数字格式化异常
Error类:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性的代码进行处理。
在已经学习过的内容中出现过的异常
int[]a=new int[5];
a[5]=10;//数组越界异常 ArrayIndexOutOfBoundsException
int []a=new int[Integer.MAX_VALUE+1];//数组长度上限异常 NegativeArraySizeException
int a=10;
int b=0;
int c=a/b;//算术运算规则异常 ArithmeticException
String a =null;
a.length();//空指针异常 NullPointerException
Object o="abc";
Integer i=(Integer) o;//类型转换异常 ClassCastException
Integer i=new Integer("1a2");//数字格式化异常 NumberFormatException
异常的体系
Throwable超类
Exception类(表示异常,是所有异常类的父类,是程序员所关心的。)
编译时发生的异常(在程序中强制去解决)
运行时发生的异常(RunTimeException类,在程序中可以不用去强制解决)
Error类(表示错误,可能是编译期错误或者系统错误,往往程序中并不处理)
异常的处理
1.默认会抛出异常的信息,然后程序停止运行
2.在编译过程中对可能出现问题的代码进行针对化的代码处理,例如使用try/catch语句
程序中预先设置好对付异常的处理办法--> 程序运行-->出现异常-->对异常进行处理-->处理完毕,程序继续运行
try/catch关键字
用来处理捕获异常的语句
try语句
检测不安全的代码块(发现异常)try块中任何一条语句发生了异常,下面的代码将不会被执行,程序将跳 转到异常处理代码块中,即catch块。因此,不要随意将不相关的代码放到try块中,因为随时可能会中断 执行。
catch语句
把抓到的类型匹配的异常捕获,保证程序能继续运行下去catch语句必须紧跟着try语句之后,称为捕获异 常,也就是异常处理函数,一个try后面可以写多个catch,分别捕获不同类型的异常,要从子类往父类的顺 序写,否则有编译错误
try{
/*int a=10;
int b=0;
int c=10/0;*/
int []a=new int[Integer.MAX_VALUE+1];//该代码就不会被第一个捕获ArithmeticException类异常的catch捕获,而会和后面的Exception类匹配
}catch(ArithmeticException a){//catch语句中的参数传入异常类
a.printStackTrace();//Exception类中的方法,可以打印异常的信息
a.getMessage();//Exception类中的方法,可以打印异常出现的原因
System.out.println("除数不能为0");
}catch(Exception e){
e.printStackTrace();
System.out.println("系统忙,请稍后再试");
}
/*
try/catch语句的执行顺序
在try中的语句中出现异常后,后面的代码不会再执行
catch语句捕获try中出现的异常,异常依次从上往下匹配异常,前面的catch匹配到了之后,后面的catch不会再执行,如果一个try对应多个catch,则根据catch中类的顺序,将基类的catch写在派生类的后面
*/
System.out.println(")))))))))))))))))");
finally关键字
一般跟在try/catch语句后面,被finally修饰的语句无论会不会出现异常都会执行,且只执行一次,在一个try/catch语句中都会只能有一个finallyfinally语句中通常会写一下必须执行的代码,例如关闭数据流的close()方法出现异常后可以也可以不使用catch捕获,也可以直接写finally来执行出现异常后的语句
语法格式:
finally{ 必须执行的逻辑 }
try{
int a=10;
int b=0;
int c=10/0;
int []d=new int[Integer.MAX_VALUE+1];//使用该代码就不会被第一个捕获ArithmeticException类异常的catch捕获,
// 而会和后面的Exception类匹配
}catch(ArithmeticException a){
a.printStackTrace();//Exception类中的方法,可以打印异常的信息
System.out.println("除数不能为0");
}catch(Exception e){
e.printStackTrace();//Exception类是所有异常类的父类,但是在catch的匹配机制中,
// 会优先匹配最接近异常的类来捕获,其次最后才是Exception类
System.out.println("系统忙,请稍后再试");
}finally{
System.out.println("aaaaaaaaaaaaaaaa");
}
//try后面直接跟finally
try{
int a=10;
int b=0;
int c=a/b;
}finally{//finally语句无论会不会出现异常都会执行,且只执行一次,在一个try/catch语句中都会只能有一个finally
System.out.println("aaaaaaaaaaaa");
}
}
finally在定义类方法时的用途:
在成员方法中如果,使用try/catch语句则如果出现异常,调用该方法的上层类无法使用知道是否出现异常与如果出现异常, 异常中的信息,故一般不会在底层方法中使用try/catch将异常捕获,而是会将异常信息返回给上层, 此时如果需要方法中必须要要执行的代码,则可以使用finally来执行,这样既不会影响上层中接下来代码的运行,也完成了该方法
在带返回值的方法中,使用finally语句,则finally会在return语句之前执行
public static void test(){
try{//成员方法中使用finally语句
int a=10;
int b=0;
int c=a/b;
}finally{//finally语句无论会不会出现异常都会执行,且只执行一次,在一个try/catch语句中都会只能有一个finally
System.out.println("aaaaaaaaaaaa");
}
}
public static int test1(){
try{
int a=10;
int b=0;
int c=a/b;
return c;
}catch(Exception e){
return -1;
}finally{//finally语句无论会不会出现异常都会执行,且只执行一次,在一个try/catch语句中都会只能有一个finally
System.out.println("aaaaaaaaaaaa");
}//在带返回值的方法中,使用finally语句,则finally会在return语句之前执行
}
throws关键字
用于在方法定义时声明在参数列表后面,声明时需要在后面接着需要声明的异常类型,表示此方法不会解决异常,而会将异常留给方法调用处解决
处理的时候有两种方式 1.使用try/catch语句 2.在调用的方法处再抛出异常给上一层 3.try/finally语句再抛异常
注:
1.任何方法都可以抛出异常,包括抽象方法
2.子类重写父类的方法,不能抛出比父类级别更高的异常(方法重写新增一条规则)
try {
test1();//顶层main方法调用需要使用try/catch语句处理异常
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static void test1() throws UnsupportedEncodingException {//一般在往上抛的时候回强制抛出编译期异常,运行期异常不强制抛出
test2();
}
public static void test2() throws UnsupportedEncodingException,NumberFormatException {//抛出是可以[抛出多个异常
" ".getBytes("utf-1111");//该代码,由于在底层的时候就是用来throws抛出了一个异常,故在调用的时候要处理该异常
//由于该调用还不在最上层故可以再使用throws抛出,该异常属于编译期的异常
}
throw关键字
在异常处理中,try语句要捕获的是一个异常对象,那么此异常对象也可以自己抛出。throw关键字写在方法体中,当程序中的业务逻辑可能不符合要求时,可以使用throw关键字在方法中主动抛出异常的对象
语法:throw new 异常类构造方法;
public static int test(int index){
int []a=new int[5];
if (index<0||index>=5){
throw new ArrayIndexOutOfBoundsException();//运行期异常,可以不强制处理,但是可以人为抛出
}
return a[index];
}
自定义异常
在程序编写的过程中,可能由于程序实际的业务逻辑需要,可以自己定义一个异常类型,该异常类型需要去继承其它的异常类
作用:用自定义异常标记业务逻辑的异常,避免与标准异常混淆
public class ScoreException extends Exception {
public ScoreException() {
}
public ScoreException(String message) {
super(message);
}
}
//实际的程序调用
public static char checkScore(int score) throws ScoreException {
if (score<0||score>100){
throw new ScoreException("分数超过界限");//编译期异常,一定需要异常处理需要抛出或者try/catch
}else if(score>=90||score<=100){
return 'A';
}else if (score>80||score<90){
return 'B';
}else{
return 'C';
}
}