第十一章 异常
学习目标
- try catch 处理异常
- 多catch处理
- throw和throws的使用
- finally代码块
- 自定义异常
- 集合框架介绍
- 集合的顶层接口Collection
- 迭代器Iterator接口
- 集合的接口List
1.异常
异常:程序在运行中出现的不正常现象就是异常。
异常的知识点不好理解,要求同学们学习异常,主要的目的记住使用格式。
1.1 异常继承体系
一切都是对象,异常也是对象。JDK为异常定义了大量的类,类之间产生继承关系。
异常中的顶级父类:
- java.lang.Throwable : 所有异常和错误的父类
- java.lang.Error : 所有错误的父类
- java.lang.Exception : 所有异常的父类
- java.lang.RuntimeExeption : 所有的运行异常父类
错误:程序中出现了错误,程序人员只能修改代码,否则不能运行。
异常:程序中出现了异常,可以把异常处理调用,程序继续执行。
1.2 Throwable的方法
- String toString() 返回异常信息简短描述 (控制台红色部分)
- String getMessage() 返回异常信息的详细描述
- void printStackTrace() 异常信息追踪到标准的错误流
- JVM对异常进行了处理:输出信息,结束程序。
- 处理异常,没有异常,继续执行程序
- 如果是jdk定义过的异常,JVM是可以自行创建的,如果没有就需要用户自个throw new 自定义异常类来抛出,方法上也要写明throws 异常类。
1.3 try…catch异常处理
try catch的异常处理的格式写法:
try{ 被检测的代码 可能发生异常的代码 }catch(异常类的类名 变量名){ 异常的处理方式 : 写什么都可以 定义变量,创建对象,调用方法,循环,判断... 只要写了catch,异常就被处理掉了 }
1.4 多catch并行处理
异常处理的代码中:try 可以跟随多个catch
好处:不同的异常,可以区别对待,分开处理。
public static void main(String[] args) { /** * myExec出现2个异常 * 写2个catch分别捕获异常 */ try { myExec(0); }catch (NullPointerException ex){ System.out.println("处理空指针异常"); }catch (ArrayIndexOutOfBoundsException ex){ System.out.println("处理越界异常"); } } /** * 定义方法,目的引发异常 * 传递参数 : 对参数进行判断 */ public static void myExec(int i){ if ( i == 0){ //引发空指针异常 String s = null; int len = s.length(); }else { //引发越界异常 int[] arr = {}; int a = arr[0]; } }
多个catch处理异常的时候,写法特别注意:如果catch中的异常类没有关系,先写后写没有区别,catch中的异常类有继承关系,父类写在最下面。
1.5 throw和throws关键字的使用
- throw关键字:只能写在方法内部,关键字的后面跟随对象的创建。
- throws关键字:只能写在方法的定义上,关键字后面跟随异常类名。
public static void main(String[] args) { /** * getArea()调用方法,方法上有异常 * 只能处理,不处理编译失败 * 在main的方法上加throws 异常没有处理,交给JVM处理 * try catch处理 */ try { int area = getArea(-10); System.out.println(area); } catch (Exception e) { e.printStackTrace(); } } /** * 功能: 计算正方形的面积 * 需要参数 : 边长 * 语法 : 方法的内部出现了异常,必须在方法定义上暴露 */ public static int getArea(int length) throws Exception{ if (length <= 0) //数据错误,导致后面的计算不能进行 //内部出现问题 throw new Exception("边长不存在"); return length * length; }
1.6 finally代码块
finally代码块跟随try ... catch使用,也有跟随try使用
finally代码块里面的程序,无论是否出现异常,都会执行,必须执行
结束JVM了,finally不执行。
主要用于释放资源
public static void main(String[] args) { try { int[] arr = {1}; System.out.println(arr[0]); }catch (Exception ex){ ex.printStackTrace(); }finally { //后期用于资源的释放 System.out.println("这里的代码,必须执行"); } }
1.7 RuntimeException异常
异常的父类是Exception,Exception类的子类RuntimeException,凡是RuntimeException和他的所有子类,都称为运行异常,非子类的称为编译异常。
- 编译异常:方法出现编译异常,调用者必须处理,否则编译失败。处理方式可以是try catch或者是throws都可以
- 运行异常:方法出现运行异常,方法的定义上,不需要throws声明,调用者也不需要处理这个异常
不要处理运行异常:程序一旦发生运行异常,请程序人员修改源码。
- 常见的运行异常
NullPointerException
空指针IndexOutOfBoundsException
越界异常ClassCastException
类型强制IllegalArgumentException
无效的参数异常
1.8 自定义异常
Java官方已经定义了大量的异常类,但是依然不够,以后做项目的时候,会出现的异常,在JDK中没有定义的,需要我们自己定义异常。
- 自定义异常,入伙,继承Exception或者RuntimeException
- 只有Exception和他的子类,才具有可抛出性
- 自定义的类中,构造方法,super调用父类构造方法,传递异常信息
/** * 自定义的异常类 * 成绩负数的异常 * 继承哪个父类呢 * * 自定义异常信息 : 继承父类 RuntimeException 带有String类型的构造方法 (String 异常信息) */ public class ScoreException extends RuntimeException{ public ScoreException(String s){ super(s); } }
public static void main(String[] args) { // int[] arr = {1}; //System.out.println(arr[2]); int avg = getAvg(-100,2); System.out.println("avg = " + avg); } /** * 计算成绩的平均分 */ public static int getAvg(int math,int chinese) throws ScoreException{ //判断成绩的数值 if ( math < 0 || chinese < 0) //手动抛出,自己定义的异常 throw new ScoreException("成绩不存在"); return (math + chinese) / 2; }