思考:
1、异常处理try…catch..finally执行过程?
- 主要依赖于try、catch、finally、throw和throws这五个关键字。(throw和throws本篇不涉及)
- try…catch…finally处理机制:
try关键字后跟一个花括号栝起的代码块(即使该代码块只有一行也不能省略花括号),简称try块。catch对应异常类型和代码块,用于表明更改catch块用于处理该种类型的异常。一个try块后可以跟多个catch块。在catch块后还可以跟一个finally块,finally块用于回收在try块里打开的资源。
在使用try…catch语句块时需要知道或注意以下几点:
1) 处理过程:代码在执行的时候,进入try块,若是在try块中出现了异常,系统会自动生成一个一场对象,该对象被提交给java运行时环境,这就是异常的抛出;在java运行时环境收到异常对象时则把该对象交给catch块处理,这个过程叫做异常的捕获;若找到相应的catch块就执行catch块中的代码,若没有找到,则运行时环境终止,程序也退出。
2) 执行一次try块只执行一个catch块
3) 有多个catch块并有继承关系的情况下必须先写子类后写父类(即先捕获小异常再捕获大异常),若写反在编译时就会报错
4) Java7提供的多异常捕获:在Java7之前,每一个catch块只能捕获一种异常,但从java7开始,一个catch块可以捕获多种类型的异常。在使用多异常捕获应注意两点:
(1) 多种异常之间用竖线( | )隔开
(2) 多种异常对象被final隐式修饰,因此程序不能对其重新赋值
- 使用finally回收资源:
有些时候我们在try块中打开了一些物理资源(例如数据库链接、网络连接和磁盘文件等),这些资源都应进行显示回收。有人说java不是有垃圾回收机制吗?java的垃圾回收机制是自动回收堆内存中对象所占用的内存,而物理资源是不会自动回收的。
finally重点学习以下几点:
1) 执行过程以及引入finally的原因:finally最后执行并且最后执行,物理资源回收放在finally块中的原因就是finally块一定会被执行。相反,若是放在try块中,在执行之前就出现异常则跳转至catch块中,则回收资源的代码不会被执行;同样的,若是放在catch块中,若不发生异常,那么catch块就不会被执行
2) 若是在catch快中有return语句,则先执行完finally中的程序后再回到catch块中并执行return语句
3) 若是在finally中有return语句,那么try块和catch块中的return语句都会失效,不会被执行
4) 若在catch块中强制退出虚拟机,如使用System.exit(1)语句,则会直接退出程序,finally也不会得到执行
- 嵌套
例如e.g.3代码所示,finally块中还嵌套了一个try…catch语句块,这种在try块、catch块或finally块中包含完整的异常处理流程的情形被称为异常的嵌套。一般对嵌套深度没有限制,但是层次太深的嵌套会降低可读性。 - Java7的自动关闭资源的try语句:
在java7之前,我们必须像e.g.3中的代码一样手动关闭文件,回收资源。在Java7中增强了try语句的功能,它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显示关闭的资源,try语句在该语句结束时自动关闭这些资源。这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close()方法。/*该类功能:打开a.txt文件,在finally块中对资源进行回收*/
/* 对代码中一些方法的解释:
* 所有异常都包含以下几种访问异常信息的常用方法:
* getMessage():返回该异常的详细描述字符串
* printStackTrace():将该异常的跟踪栈信息输出到标准错误输出
* printStaceTrace(PrintStack s):将该异常的跟踪栈信息到执行输出流
* getStackTrace():返回该异常的跟踪栈信息
*/
public class FinallyTest {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
}catch(IOException ioe) {
System.out.println(ioe.getMessage());
return; //①
System.exit(1); //②
}finally {
if(fis != null) {
try{
fis.close();
}catch(IOException ioe) {
ioe.printStackTrace();
}
}
System.out.println("执行finally块里的资源回收!");
}
}
}
2、throw与throws差异?
1、throw 在方法体内使用,throws 在方法声明上使用;
2、throw 后面接的是异常对象,只能接一个。throws 后面接的是异常类型,可以接多个,多个异常类型用逗号隔开;
3、throw 是在方法中出现不正确情况时,手动来抛出异常,结束方法的,执行了 throw 语句一定会出现异常。而 throws 是用来声明当前方法有可能会出现某种异常的,如果出现了相应的异常,将由调用者来处理,声明了异常不一定会出现异常。可以理解为throw是主动(在方法内容里我们是主动捕获并throw的),而throws是被动(在方法上是没有捕获异常进行处理,直接throws的)3、自定义异常要求?
自定义异常:java提供的异常类,不够我们使用,需要自己定义一些异常类
格式:
public class XXException extends Exception|RuntimeException{undefined
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
注意:
1.自定义异常类一般是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须继承Exception或者RuntimeException
继承Exception:那么自定义的异常类就是一个编译期异常,如果出现了编译期异常就必须处理,要么throws ,要么try catch
继承RuntimeException:那么自定义的异常就是一个运行期异常,无需处理,交给虚拟机处理,中断处理。
4、覆盖方法定义时,声明异常有何限制?
异常在子父类覆盖时的体现
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者异常的子类
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出分父类异常的子集。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常
如果子类方法发生了异常。就必须要进行try处理,绝对不能抛。
5、举出5个常见系统异常?
常见系统定义的异常 | 异常的解释 |
---|---|
ClassNotFoundException | 未找到要装载的类 |
ArrayIndexOutOfBoundsException | 数组访问越界 |
FileNotFoundException | 文件找不到 |
IOException | 输入、输出错误 |
NullPointerException | 空指针访问 |
ArithmeticException | 算术运算错误,如除数为0 |
NumberFormatException | 数字格式错误 |
InterruptedException | 中断异常,线程在进行暂停处理时(如:睡眠) 被调度打断将引发该异常。 |