1.异常(理解)
-
概述:异常就是Java程序在运行过程中出现的错误
-
引入:IO流操作的上传和下载图
-
异常的分类
程序的异常:Throwable //表示java中所有的问题及异常,是以下两种异常的父类 -
严重问题:Error。这种异常不处理,因为不是用程序能处理的。这种一般都是很严重的,比如内存溢出
-
一般问题:Exception
a:编译期问题:不是RuntimeException的异常。这种异常是必须处理的,因为不处理,编译就不能通过
b:运行期问题:RuntimeException。这种异常我们也不处理,这个异常会出现肯定是我们的代码不够严谨,需要修正代码
-
JVM的默认处理方案
-
如果程序出现问题,我们没有做任何处理,最终jvm会做出默认的处理:把异常的名称,原因及出现的问题等信息输出在控制台。同时还会结束程序
-
这个处理不够好,于是我们可以自己处理
-
自己处理异常的方式
-
try…catch…finally
A:一个异常的处理处理格式: try { 可能出现问题的代码; }catch(异常名 变量) { 针对问题的处理; }finally { //finally也可以省略 释放资源; } 注意: try里面的代码越少越好 //否则会使java开辟太多用来处理异常的空间,占用空间 catch里面必须有内容,哪怕是给出一个简单的提示
B:多个异常的处理
a:每一个异常写一个try...catch b:写一个try,多个catch try{ ... }catch(异常类名 变量名) { ... } catch(异常类名 变量名) { ... } ... c:JDK7出现了一个新的异常处理方案: try{ ... }catch(异常名1 | 异常名2 | ... 变量 ) { ... } c虽然比b简洁,但还是有一些限制: <1>处理方式是一致的 //但实际开发中挺常用,因为很多时候就是针对同类型的问题,给出同一个处理) <2>多个异常间必须是平级关系
注意点<1>:
(1):能明确的尽量明确,不要用大的来处理 //否则影响效率
(2)平级关系的异常谁前谁后无所谓,如果出现了子父关系,父必须在后面
注意点<2>
一旦try里面出了问题,就会在这里把问题给抛出去,然后和catch里面的问题进行匹配;
一旦有匹配的,就执行catch里面的处理,然后结束了try…catch,继续执行后面的语句 -
throws 抛出:有时,我们没有权限去处理某个异常;或者处理不了,就干脆不处理了.为了解决出错问题,Java针对这种情况,提供了另一种处理方案:抛出
处理格式: throws 异常类名 //异常类名可以跟多个,用逗号隔开即可 注意: (1)这个格式必须跟在方法的括号后面 (2)尽量不要在main方法上抛出异常
2.编译时异常和运行时异常的区别
-
编译期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译
-
运行期异常:无需显示处理,也可以和编译时异常一样处理
编译期异常抛出,将来调用者必须处理
运行期异常抛出,将来调用可以不用处理。当然也可以选择处理
3.异常中常见的方法:
-
public String getMessage():异常的消息字符串
-
public String toString():返回异常的简单信息描述:
此对象的类的全路径名": "调用此对象getLocalizedMessage()方法的结果
//这里的结果,默认返回的是getMessage()的内容) -
printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。把信息输出在控制台
暂时先用这个,虽然和JVM的默认处理输出的效果一样
但有一点不同:用这个方法,即使出现异常后面的代码依旧可以执行
以后开发中,该方法会被index.html(跳转到某个指定的页面)
代替
4.throw
-
概述:在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出
-
throws的区别(面试题)
-
throws
用在方法声明后面,跟的是异常类名 可以跟多个异常类名,用逗号隔开 表示抛出异常,由该方法的调用者来处理 throws表示出现异常的一种可能性,并不一定会发生这些异常
-
throw
用在方法体内,跟的是异常对象名 只能抛出一个异常对象名 表示抛出异常,由方法体内的语句处理 throw则是抛出了异常,执行throw则一定抛出了某种异常
5.选择哪个方案处理异常?
- 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这时用throws
- 区别:
- 后续程序需要继续运行就try //所以开发时一般用这个
- 后续程序不需要继续运行就throws //一般遇到方法里面用throw抛异常时,方法定义上都会用throws抛
- 例:
感冒了就自己吃点药就好了,try
吃了好几天药都没好结果得了H7N9,那就得throws到医院
如果医院没有特效药就变成Error了
6.finally
-
概述:被finally控制的语句体一定会执行 //但如果在执行到finally之前,jvm退出了,就不能执行了
-
格式:
try...catch...finally...
-
作用:用于释放资源,在IO流操作和数据库操作中会见到
-
面试题一:final,finally和finalize的区别
-
final:最终的意思,可以修饰类,成员变量,成员方法
修饰类时,类不能被继承
修饰变量时,变量是常量
修饰方法时,方法不能被重写 -
finally:是异常处理的一部分,用于释放资源
一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了 -
finalize:是Object类的一个方法,用于垃圾回收,详见
ppt第七章第40页的备注
-
面试题二:如果catch里面有return语句,finally里面的代码还会执行吗?如果会,是在return前还是后?
-
会;前
try { System.out.println(a / 0); a = 20; } catch (ArithmeticException e) { a = 30; return a; /*return a在程序执行到这一步的时候,这里不是return a而是return 30,这个返回路径就形成了 * 但它发现后面还有finally,所以继续执行finally的内容,a=40 * 再次回到以前的返回路径,继续走return 30; */ } finally { a = 40; //所以准确的说,finally的执行是在return的中间 } return a;
-
try…catch…finally的格式变形
-
try…catch…finally
-
try…catch
-
try…catch…catch…
-
try…catch…catch…finally
-
try…finally:这种做法的目前是为了释放资源
7.自定义异常
- 概述:java不可能考虑到所有的情况,所以在实际开发中,我们可能需要自己定义异常。而自己随意的写一个类,是不能作为异常类来看的,要想你的类是一个异常类,两种方式:
- 让你写的这个类继承Exception(调用要自己处理),并提供无参构造和一个带参构造即可 //带参构造中只需要有一条
super(message);
语句 - 让你写的这个类继承RuntimeException,其它都同上一种
8.异常注意事项:
- 子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类 //最好是相同的
- 如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集(也就是其中几个),子类不能抛出父类没有的异常
- 如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常。如果子类方法内有异常发生,那么子类只能try,不能throws //假如eclipse点鼠标修正异常时,只出现了try,就说明是这种情况