思考:

1、异常处理try…catch..finally执行过程?

  1. 主要依赖于try、catch、finally、throw和throws这五个关键字。(throw和throws本篇不涉及)
  2. 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隐式修饰,因此程序不能对其重新赋值

  1. 使用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也不会得到执行

  1. 嵌套
    例如e.g.3代码所示,finally块中还嵌套了一个try…catch语句块,这种在try块、catch块或finally块中包含完整的异常处理流程的情形被称为异常的嵌套。一般对嵌套深度没有限制,但是层次太深的嵌套会降低可读性。
  2. Java7的自动关闭资源的try语句:
    在java7之前,我们必须像e.g.3中的代码一样手动关闭文件,回收资源。在Java7中增强了try语句的功能,它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显示关闭的资源,try语句在该语句结束时自动关闭这些资源。这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close()方法。
    1. /*该类功能:打开a.txt文件,在finally块中对资源进行回收*/
    2. /* 对代码中一些方法的解释:
    3. * 所有异常都包含以下几种访问异常信息的常用方法:
    4. * getMessage():返回该异常的详细描述字符串
    5. * printStackTrace():将该异常的跟踪栈信息输出到标准错误输出
    6. * printStaceTrace(PrintStack s):将该异常的跟踪栈信息到执行输出流
    7. * getStackTrace():返回该异常的跟踪栈信息
    8. */
    9. public class FinallyTest {
    10. public static void main(String[] args) {
    11. FileInputStream fis = null;
    12. try {
    13. fis = new FileInputStream("a.txt");
    14. }catch(IOException ioe) {
    15. System.out.println(ioe.getMessage());
    16. return; //①
    17. System.exit(1); //②
    18. }finally {
    19. if(fis != null) {
    20. try{
    21. fis.close();
    22. }catch(IOException ioe) {
    23. ioe.printStackTrace();
    24. }
    25. }
    26. System.out.println("执行finally块里的资源回收!");
    27. }
    28. }
    29. }

    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 中断异常,线程在进行暂停处理时(如:睡眠)
被调度打断将引发该异常。