第四部分 异常
程序在运行或者编译的过程当中发生了问题称为异常,异常处理的时候系统进行是模糊匹配,也就是说只要处理的异常大于发生的异常就可以了
假设调用了一个不是自己写的方法,该方法执行某些有风险的任务,可能会在运行期间出状况,你必须认识到该方法的是有风险的,你得写出发生状况时的处理代码,未雨绸缪
面试题:
使用什么方式可以使程序停止运行?
1程序发生未处理的异常
2使用System.exit(int status)
面试题:java代码是从上往下执行,所以当try跟多个catch,如果第一个catch已经catch住异常,那么下面的catch就不会继续执行
运行期出现的错误
Throwable:
Error:JVM内部错误,无法处理
Exception:外在因素导致一般性错误
(1)RuntimeException 可以不捕获,出错后改代码(逻辑异常)
(2)其他(编译异常):需捕获
异常的处理方式
(1)抛出异常:格式 throws 异常类名 //调用者必须要处理main,不然就漏给虚拟机了
(2)如果把有风险程序代码放在try/catch块,编译器会放心很多,try/catch块会告诉编译器你确实知道所调用方法会有风险,并且也已经准备好处理它。注:try{}和catch{}之间不可以有代码
捕获异常 try { 把有风险的程序放在try块中;
}catch(异常类 变量名){
用catch块摆放异常状况处理程序;} //常用e.printstackTrace()打印异常名+异常信息+异常位置
finally{一定执行代码; 一般用于关闭资源
}
注意:try{ }大括号里定义的变量,finall里不能调用
//虽然异常也具有多态,但应该先抓小错再抓大错,因为直接抓异常的父类,可能会搞不清到底在哪里出了错
在继承树上的层次越高,“篮子”也越大,当你沿着继承树往下走,异常类就会越来越有特定的取向,catch的“篮子”越来越小,也就更容易确定是到底在哪里出了错误
如果try的代码没出错,则跳过catch继续执行,如果try的代码出错,则只执行catch内容(出错代码之后catch之前代码不执行),finally里面放的是不管出不出错都要执行的代码,如果try,catch里有return语句,finally里的内容一样会执行。
a、finally中的代码总是会执行吗?
答:no,如果一个方法内在执行try{}语句之前就已经return了,那么finally语句指定不会执行了。因为它根本没有进入try语句中
如果在一个try语句中调用System.exit(0);方法,那么就会退出当前java虚拟机,那么finally也就没有执行的机会了。
b、finally在return之前执行还是在return之后执行?
答:很多人可能会说在return执行之前执行。我的答案是在return中间执行,是不是很特别,请按下面的例子:
请问输出的结果是多少呢?
正确答案是:1
下面我来讲解一下这个程序的执行过程,
首先程序在执行到try{}语句中的return方法后,就会先返回相应的值,并把相应的值存储在一个临时栈中去保存这个结果。这时临时栈中存储的值为1。
但是程序不会立刻返回,转而回去执行finally中的方法,++x,在finally执行完后,方法全部执行完,这时会再次调用return方法,注意这时不在是返回值,而是告诉主调程序,被调程序已经执行完了,你可以接着去执行你主程序的其它方法了。但是请注意,此时返回的值还是原来保存在临时
栈中的值1。
标识异常
遇到throw 程序就结束了
人工抛出异常(JVM不认为是错的,但是不合乎清理) 等同自定义异常
//人工抛出异常后,当运行此方法或调用此方法的时候,程序会认为这有一个错误,必须throws或try catch
只有声明了此处是一个需要捕获的异常的时候,catch才能去抓住它。类似于抓嫌疑人,只有嫌疑人被通缉的时候,其它地方的警察才会知道这是一个嫌疑犯,然后取抓它
创建用户自定义异常类:必须继承现有异常类 1.Exception 2.RuntimeException常用
class ( ) extends(){
}
创建自定义异常的步骤就是,先创建一个异常类继承原来的异常,然后在try catch中,用if判断,如果出现这种情况,就标识这个异常。和直接标示异常原有异常相比的区别就是,打印的异常信息不同了,打印出的是你自定义的异常类的信息。 其它和抛出原有异常的效果一模一样
面试题
举出常用的五种运行时异常
NullPointException空指针异常
IllegalArgumentException方法参数异常
ClassCastException类型强制转换异常
IndexOutOfBoundsException:索引下标越界异常