关于异常机制(学习笔记)
异常的概念:
异常模拟的是现实生活中“不正常的”事件。java中采用“类”去模拟异常,类是可以创建对象的,创建的异常对象就是真正的异常事件。比如:
“抢劫”就是一类异常。——>类
“张三被抢劫”就是一个异常事件——>对象
异常的作用:
java语言为我们提供一种完善的异常处理机制,作用是:程序发生异常事件之后,为我们输出详细的信息,程序员通过这个信息,可以对程序进行一些处理,使程序更加健壮。
如上,发生异常会提示异常信息,并且发生异常后程序不再往下执行。
异常的继承结构:
众所周知,再java中异常是由“类”来表现的,那么类与类之间肯定是由继承结构的。以下是异常的继承结构图:
可以看到异常(Exception)和错误(Error)都是继承了Throwable类的,所以都是可抛出的。Error是不可处理,一旦发生直接退出JVM,而Exception是可以处理的。Exception又分为编译时异常和运行时异常。编译是异常是需要再编写程序时就对异常进行处理的,否则程序编译不能通过,而运行是异常则不需要。
异常的处理
处理异常又两种方式:
-
声明抛出:在方法后面加 throws 异常。
抛出异常等于推卸责任,将异常抛给调用者,等待调用者解决异常,调用者也可以继续抛出,知道异常被捕捉。
只要采用的是throws 处理异常,发生异常的代码之后的代码会停止运行。
但是如果一直上抛,抛给main方法,main方法继续上抛,抛给JVM之后,JVM就会终止程序的执行。 -
捕捉:try……catch……
捕捉才是真正的解决异常,只有将异常捕捉了,异常才会消失。语法: try{ 可能出现的异常代码; }catch(异常类型1 变量){ 处理异常的代码; }catch(异常类型2 变量){ 处理异常的代码; }….. try语句块中一代发生异常,下面的代码则不会执行,直接转入catch语句块。 catch语句块可以多写几个。 但是从上到下catch,必须从小类型异常到大类型异常进行捕捉。 最多执行1个catch语句块。执行结束之后try….catch..就结束了。
在JDK8的新特性中,catch语句中可以写多个异常类型,使用 “|” 划分,如下:
getMessage()方法与printStackTrace()方法
- getMessage:取得异常描述信息
- printStackTrace:取得异常堆栈信息
finally语句块
-
finally语句块可以直接和try语句块联用。Try……finally….
try{ }finally{ }
-
Try……catch……finally……也可以
try{ }catch(){ }finally{ }
-
在finally语句块中的代码是一定会执行的。
除非在try语句块中直接退出JVM,finally就不执行了。
所以finally语句块是比较有保证的,可以执行一些在程序结束前必须要执行的语句,比如流的关闭。
finally面试题
根据我们以上所说,finally是在程序结束前执行的,那上图中的代码本应该是先执行finally中的i++
语句,然后才执行return语句的,最终返回结果应该是101才对,但是最终结果确实100。这是什么原因呢?
这里我们需要看一下反编译代码:
通过上图我们就可以清晰的看懂原理了,返回的其实不是i
,而是j
。
final、finally、finalize的区别
- final是关键字:
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量无法重新赋值
…… - finally是关键字
需要和try语句块联合使用,
finally语句块中的代码一定会执行。 - finalize是标识符
是一个Object类中的方法名,
这个方法是由垃圾回收器GC负责调用的。