1.什么是异常
定义:在程序运行过程中出现的错误,称为异常
。异常就是程序运行过程中出现了不正常现象导致程序的中断。
在Java中,把各种异常现象进行了抽象形成了异常类。
2.1 异常的类图结构
2.2error和exception的区别?
Error类和Exception类的父类都是Throwable类,他们的区别如下:
Error类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。对于这类错误的导致的应用程序中断,仅靠程序本身无法恢复和预防,遇到这样的错误,建议让程序终止。
Exception类表示程序可以处理的异常,可以捕获且可能恢复。这种异常是由与程序设计的不完善而出现的问题,遇到这类异常,应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
Exception类又分为未检查异常(UnCheckedException)和受检查的异常(CheckedException)。
运行时异常ArithmeticException,IllegalArgumentException编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。
而受检查的异常,要么用 try…catch 捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。
3.常见的异常类型
Exception 是异常父类
4.异常的 处理
运行程序异常(系统异常) 不需要预处理,可以通过规范代码避免这类异常。
受检异常(编译异常),必须处理,否则编译报错,有两种预处理方式。
- 捕获处理
- 抛出处理
4.1异常捕获处理
4.1.1 try 、catch、finally
- try 中包含了可能产生的异常代码
-
try
后面是catch
,catch可以有一个或多个,catch中是需要捕获的异常 finally
表示,不管是出现异常,还是没有出现异常,finally里的代码都执行,finally和catch可以分开使用,但finally必须和try一块使用,如下格式使用finally也是正确的
4.1.2 异常处理
4.1.3 捕获异常的顺序
异常的捕获:一般按照由小到大的顺序,也就是先 截获子异常,再截获父异常。
代码分析:将IOException放到前面,会出现编译问题,因为IOException
是FileNotFoundException
的父类,所以截获了IOException异常后,IOException的子异常都不会执行到,所以再次截获FileNotFoundException没有任何意义
因为 代码执行先捕获了父类异常,就不再执行子异常了没有意义了
正确代码
4.2 throws抛出处理
定义方法时,如果方法体中有受检(编译时)异常需要处理,可以捕获处理,也可以抛出处理。
处理异常时,使用throws抛出处理:
除非:跳出 系统语句段,System.exit(1);
throw
4.3 getMessage()和printStackTrace()
如何取得异常对象的具体信息,常用的方法主要有两种:
- 获取异常描述信息
使用异常对象的getMessage()方法,通常用 打印日志时
- 取得异常的堆栈信息
使用异常对象的printStackTrace()方法,比较适合于程序调试阶段
5 异常相关的面试题
5.1 谈谈你Java异常处理机制的理解?
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为 java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception。
- Error: 表示应用程序本身无法克服和恢复的一种严重问题。
- Exception: 表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常。
系统异常
系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉。
例如,数组下标越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException)。
普通异常
普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
Java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try…catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以编译器不强制用try…catch处理或用throws声明,所以系统异常也称为unchecked异常。
面试题 执行顺序
1. 先 try --> catch -->finally -->return
2. System.exit(1) 退出程序系统则不执行
注:只有在 try 里面通过 System.exit(0) 来退出 JVM 的情况下 finally 块中的代码才不会执行,其他 return 等情况都会执行finally 代码块。
5.2 throw 和 throws 的区别?
- throw
throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throw具有向外抛出异常的动作,所以他抛出的是一个异常实例,执行throw一定是抛出了某种异常
throw一般用于抛出自定义异常。
- throws(使用者调用者 方法体外)
throws语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理
throws主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的异常的类型。
throws表示出现异常的一种可能性,并不一定会发生这种异常。
5.3 final、finally、finalize 的区别?
- final
用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
- finally
异常处理语句结构的一部分,表示总是执行。
- finalize
finalize是Object类的一个方法,当java对象没有更多的引用指向的时候,会被垃圾回收器回收
5.4 error和exception的区别?
Error
类 和 Exception
类的父类都是Throwable
类,他们的区别如下:
- Error 类一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出。仅靠程序本身无法恢复和预防
- Exception类表示程序可以处理异常,可以捕获恢复
Exception 又分 检查异常 和 受检查异常
检查异常运行时异常ArithmeticException,IllegalArgumentException编译能通过,但是一运行就终止了,程序不会处理运行时异常,出现这类异常,程序会终止。
受检查的异常,要么用 try…catch 捕获,要么用throws字句声明抛出,交给它的父类处理,否则编译不会通过。
5.5 throw new Exception 自定义异常
5.7 java中如何编写自定义异常?
自定义异常通常继承于Exception
或RuntimeException
,到底继承那个应该看具体情况来定。
6.总结
java中异常相关的知识,
- 异常的分类
- 受控异常和非受控异常的区别
- 异常的捕获和抛出处理
- 异常的捕获顺序,先捕获小的,再捕获大的
- 方法覆盖和异常的关系
- 异常的5个关键字try、catch、finally、throws、throw