黑马程序员--Java基础之异常Exception
一、异常概述
1、异常是什么:是对问题的描述,将问题进行对象的封装。
2、异常体系:Throwable:
|---Error,严重的问题,对于Error一般不编写针对性的代码对其进行处理。
|---Exception,非严重的问题,可以针对性处理。
|---RunTimeException;
异常体系的特点:异常体系中的所有类及对象都具有可抛性。即都可以被throws和throw关键字所操作。只有异常体系具备这个特点。
二、异常的两种处理方式
1、第一种try()catch(){}finally{}处理。
try{
需要被检测的代码;
}catch(异常类 变量){//这里的变量接受try代码中检测到的异常如:Exception(父类) e = new 异常类();
处理异常的代码(处理方式);
}finally{
一定会执行语句;
}
finally语句块中存放的是一定会被执行的语句,通常用于关闭资源。finally有一种情况是执行不到的:前面有System.exit(0);即系统退出。
e.getMessage();//异常信息
e.toString();//异常名称 : 异常信息
e.printStackTrace();//打印追踪信息。异常名称+异常信息+异常出现的位置。jvm默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈跟踪信息。
特殊:method(){
try{throw newException();}catch(Exception e){}//这样编译也是可以通过的,因为这个抛出的异常立马在内部catch中解决掉了。
}
2、第二种处理方式,将异常抛出throws和throw,以及二者区别。
throws用于函数上,用于抛出异常类,可以同时抛出多个,用逗号分隔。
throw用于函数内部,抛出异常对象:thrownew 。。。();
当函数内有throw抛出异常对象,并且trycatch中没有处理此异常,那么必须在函数上声明一下,否则编译失败。(RuntimeException及其子类除外)。
3、多异常的处理。
多异常抛出,如:intdiv(int a,int b) throws Arit....Exception,Ari...Exception
这时需要有两个catch(具体的异常声明){},或者一个catch(Exception e){}但是这样并不是针对性的处理,建议使用更针对性的处理。
对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最后面。否则编译错误!建议在进行catch处理时,一定要定义具体处理方式。正规使用异常日志。
4、运行时异常RuntimeException,特殊的Exception子类。
异常分为两种
*编译时被检测异常:编译时如果没有处理(throws或者try catch),编译失败。该异常被标识,代表可以被处理。
*运行时异常:编译时不检测,所以在编译时不需要处理,编译器不检查。该异常的发生,建议不处理让程序停止,需要对代码进行修正。
如果是RuntimeException的子类,在函数内抛出异常,函数上不声明,编译一样通过。也不需要让调用者处理,当该异常发生,希望程序停止,因为在运行时出现了无法继续运算的情况,希望停止程序后对代码进行修正。自定义异常时,如果该异常的发生无法再继续进行运算,就让自定义异常继承RuntimeException。
5、当捕获到的异常本功能处理不了时,可以继续在catch中抛出;如果该异常处理不了且不属于该功能出现的异常,可以将异常转换后,再抛出和该功能相关的异常; 或者异常可以处理,但需要将异常产生的和本功能先关的问题提供出去,让调用者知道并处理。也可以将捕获异常处理后,转换成新的异常。比如汇款例子。
三、自定义异常
有些项目中出现的特有问题并未被java所描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想,进行自定义的异常封装。
1、自定义异常,需要手动抛出:if() throw new FuShuException;//通过throw关键字抛出
2、自定义异常必须是自定义类继承Exception。因为这样才具备可抛性。
3、自定义异常练习
需求:毕老师用电脑上课
问题:电脑蓝屏,电脑冒烟
问题描述,封装成对象。
讲师问题:课时无法继续
代码示例:
/*
需求:毕老师用电脑上课
问题:电脑蓝屏、电脑冒烟
老师课时计划无法完成
对问题进行描述封装成java对象
*/
classLanPingException extends Exception{
LanPingException(String msg){
super(msg);
}
}
class MaoYanExceptionextends Exception{
MaoYanException(String msg){
super(msg);
}
}
classNoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
class Computer{
private int state = 2;
Computer(){}
public void run() throws LanPingException,MaoYanException
{ if(state== 2)
throw newLanPingException("电脑蓝屏了,可以解决的");
if(state == 3)
throw newMaoYanException("电脑冒烟了 没办法了");
System.out.println("theComputer is running...");
}
public void reset(){
System.out.println("电脑重启了,OK");
state = 1;
}
public int getState(){
return state;
}
}
class Teacher{
private String name;
private Computer c;
Teacher(){}
Teacher(String name){
this.name = name;
this.c = new Computer();
}
public void Jiangke()throws NoPlanException
{
try
{
c.run();
}
catch(LanPingException e)
{
System.out.println(e.getMessage());
c.reset();
int x = c.getState();
System.out.println(x);
//下面如果还要运行run()方法必须还要处理一下,也就是需要try catch一下
//try
//{c.run();
//}catch(..){...}
}
catch(MaoYanException e) //throwsNoPlanException
{
System.out.println(e.getMessage());
throw newNoPlanException("课时计划完不成了,放假吧");
}
System.out.println("theTeacher is working..");
}
public void test()
{
System.out.println("做点练习吧");
}
}
class Test9_12{
public static void main(String[] args){
Teacher t =new Teacher("老毕");
try
{
t.Jiangke();
}
catch(NoPlanException e)
{
t.test();
System.out.println(e.getMessage());
}
}
}
四、覆盖时的异常特点
1、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者异常的子类(如使用中用到多态。。)
2、如果子类中真的还有其他异常,这个异常一定要在内部catch中解决掉,不能再抛。
3、如果父类中抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子类。
4、如果父类或者接口的方法中没有异常抛出,子类覆盖时,也不可以抛出异常。
如果子类方法发生了异常,就必须在catch中处理掉,绝对不能抛出。
五、异常的好处
1、将问题进行封装。
2、将正常流程代码和问题处理代码分离,方便阅读。