异常类层次
异常分RuntimeException和非RuntimeException,RuntimeException下有许多子类
Error
- main方法内调用自身方法,则创建无数个args
每执行一次,则进行一次形参传递,分配无数多个空间,都为args
但栈空间有限,报异常
- 创建对象实体,堆空间有限,报内存异常
异常类型一:运行时异常
回顾bank类可能的空指针异常
最后一行代码编译期就报错了,轮不到运行时异常
上方代码异常,则下方代码不再执行
异常类型二:编译时异常
强调:不是语法错误(概念明晰)
程序功能:从相对路径(工程目录下)读取文件,将文件内容打印到控制台上
即使有文件,也会报编译时的异常(万一没有呢)
修改:添加异常处理
异常处理
异常处理概述
要点
- 捕捉到异常,抛出对应的异常类型的对象
- 抛给方法的调用者(抛给JVM)
要点:
- 变量的作用范围
- catch块执行顺序,若有一符合,直接执行,后跳出
- 异常处理了,其后代码继续执行
- finally一定执行,不管异常有无或return
运行时异常,处不处理都一样,都会抛出错误,而编译不处理,程序都通不过
处理异常法一:try/catch块
try/catch块的快速创建
选中代码块,然后如图操作
自动异常的处理方法
自定义异常处理方法
自动创建的异常处理方法:
e.printStackTrace():打印出现异常的堆栈信息
e.getMessage():获取信息,返回String类型
try/catch块异常处理实例(文件输出)
- 有BUG,当read方法出现异常,跳到异常处理处,输入流会不关
- 输入流稀有,用完要关闭
- finally内仍然要进行异常处理
- 异常处理的嵌套
手动抛出异常
上述代码采用踢皮球异常处理方式
不进行异常处理,程序编译正确
不进行异常处理,程序编译报错
- 原因:
运行时异常可不显式处理,编译异常一定处理
自定义异常类
要求throwable体系下的异常类对象,所以要继承
- 全局常量:序列化机制,通过序列号唯一确定异常类对象
- 可直接throws+该类对象(运行时异常,可不显式处理)
若父类改为Exception(包括编译时异常),则要显式处理
- 关注syso(s)的位置,放在try块内,若有异常,则不打印,否则,若打印放在最后面,会执行(因为写了异常处理语句)
异常方法的重写
原因:
- 编译时看等号左边,即catch父类方法的异常类型
- 运行时看右边,子类方法的异常类型小于父类异常类型,才能捕获异常,否则,超出父类方法的异常类型,则捕获不到异常,BUG!
finally练习
JDBC:事务,出现异常,回滚事务(后续学习)
- 返回值为2
- 有异常,则先打印堆栈信息,再finally语句块
- 无异常,则直接finally语句块
- 关注执行顺序,先执行finally块,然后输出异常信息
总结:finally块内一定执行,再输出异常信息
返回3,程序遇到return跳出当前方法
- 若不写finally,出现异常,则程序退出,后面代码不执行(明白finally意思,不矛盾)
处理异常法二:声明抛出异常
踢皮球的既视感,自己不处理,只是缓兵之计,try/catch才是解决问题的方法
抛出异常给方法的调用者,若上级一直没人处理,则一层层直到JVM(即由编译时异常到运行时异常)
-
- 异常是否合并写,按处理方式是否一致决定
- 写为throws Exception:多态性,创建的具体异常类对象赋给Exception类型,向上转型
异常总结(重点)
- 关注throw和throws的区别,会表达
- catch可选,可以没有
- throws若一直踢皮球,最后给JVM,则变成运行时异常
- 可通过throws将各方法的异常集中到主方法来统一处理
- 手动抛,异常类对象可自定义
异常练习
练习1(体会流程)
输出结果:
- 有异常处理的语句,methodB方法会继续执行
- throw类似return,会退出当前语句
修改如下:
输出结果:
练习2(综合练习)
题目:
可能产生异常的方法
- 类型转换也包含在try块内,可能类型转换异常等
- ecm方法抛出自定义异常类对象,交给主方法处理,即通过try/catch块处理
自定义异常类
输入参数
通过右键,Run Configuration,进行交互