------<ahref="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
黑马程序员—— 8,关于异常Exception的知识点
异常:程序运行的时候遇到的特殊问题
一般程序遇到的问题有两种:
严重的Error(错误)这一类就没有办法解决;
非严重Exception(异常)这一类就有解决方法。
以以下程序为例子:
图1
图1中的z=x/y的算术中由于除数为0,所以,编译时候会出现图2所示
图2
虚拟机编译到第18行的时候就出问题了,就不会继续读代码了。
当然,还有另外一种写法:
图3
图3的程序编译结果也是类似的
Exception下面还有很多异常子类,所以,Exception是所有异常的【根】,较为常见的异常就是RuntimeException(运行时异常),在所有的异常类中,除开RuntimeException(运行时异常)和自己的子类,其他的都叫做非运行时异常。
遇到异常,也有对应的处理方法:
——————分割线————————
异常的处理方式:
try
{
被检测的代码;
}
catch (异常类 变量)
{
针对异常的处理方式;
}
finally
{
一定执行的语句;
//这是不过有没有异常都会执行的语句
}
需要特别注意的是:即便try模块里面有return,程序在执行的时候依旧会执行到finally模块;但是如果try模块里面有System.exit(0);这句话的话,那么程序就不会执行到finally模块了。
——————分割线————————
使用这种异常处理方式如图4所示
/*
异常:程序运行时出现不正常情况
问题有两种:严重Error;非严重Exception(异常)
异常的处理方式:
try
{
被检测的代码;
}
catch (异常类 变量)
{
针对异常的处理方式;
}
finally
{
一定执行的语句;
}
String getMessage();这个是异常类里面常用来获取异常信息的方法
*/
class Chufa//除法类
{
int cf(int x,int y)
{
return x/y;
}
}
class Yichang//自己定义的异常类(汉语拼音)
{
public static void main(String[] args)
{
Chufa a=new Chufa();//建立Chufa类的对象
try
{
int z=a.cf(15,0);//直接调用cf方法
System.out.println("没有问题");
}
catch (Exception e)
{
System.out.println("除数为0啦!!!");
}
finally
{
System.out.println("这是finally模块运行的结果");
}
System.out.println("哈哈");
//System.out。println("结果是"+z);
//第52行这句话放在这里编译会出问题,因为z由于前面编译出问题没有给出确切值
}
}
图4
图4运行结果如图5所示
图5
图5中编译运行的结果里面根本就没有图4中第40行的执行结果,说明第39行的int z=a.cf(15,0);除了问题,那么异常出现,程序跳转到catch代码块里面接着执行下去了。
而String getMessage();这个是异常类里面常用来获取异常信息的方法,该方法本来就是异常类里面有的方法。
异常类变量.toString(); //用来显示异常名字和异常信息
异常类变量.printStackTrace(); //用来显示异常名字,异常信息,异常位置
————分割线——————
以下图6是关于异常的声明
class Chufa//除法类
{
int cf(int x,int y) throws Exception//声明该方法可能有问题
/*
因为声明了该方法可能有问题,
所以调用该方法的时候要么扑捉异常要么抛出异常
*/
{
return x/y;
}
}
class Yichang2//自己定义的异常类(汉语拼音)
{
public static void main(String[] args) throws Exception//把异常抛给了虚拟机
{
Chufa a=new Chufa();//建立Chufa类的对象
int z=a.cf(15,0);//直接调用cf方法
/*
如果是int z=a.cf(15,0);那就出了异常,
那么主函数又把异常抛给了虚拟机
相当于异常对象一次又一次的被往外面抛出去
*/
System.out.println("结果是"+z);
}
}
图6
关于出现多异常的情况图7我们也是应该讨论:
class Chufa//除法类
{
int cf(int x,int y) throws ArithmeticException,ArrayIndexOutOfBoundsException
//声明了多个异常
{
int[] a= new int[x];
System.out.println(a[x]);
return x/y;
}
}
class Yichang3
{
public static void main(String[] args)
{
Chufa k=new Chufa();
try
{
int daan=k.cf(4,0);
System.out.println("除法结果是"+daan);
}
catch (ArithmeticException e )//处理除数为0的异常
{
System.out.println("除数为0");
}
catch (ArrayIndexOutOfBoundsException e)//处理除数为0的异常
{
System.out.println("数组角标越界了");
}
System.out.println("Hello World!");
}
}
图7
图7运行结果为图8所示
图8
把程序中的int daan=k.cf(4,1);更改为int daan=k.cf(4,0);接着继续编译运行,结果还是图8所示的结果一样的。说明程序在执行当中遇到“数组角标越界”和“除数为0”这两个异常当中的一个的时候就会跳转到对应的catch代码块部分继续执行,所以,不可能同时执行两个catch代码块。
但是,真正在编写代码开发的时候,catch代码块里面都是生成异常文件(日志),给网络维护员看的。
以下是关于自己定义异常的实现如图9
/*
自定义异常
*/
class Exception1 extends Exception
class Exception1 extends Exception
{
Exception1(String msg)
{
super(msg);
}
}
class Lizi
{
int chufa(int x,int y) throws Exception1//有异常对象抛出要在该方法上声明
{
if(y==0)
throw new Exception1("这是除数为0的异常");
//抛出一个异常对象
return x/y;
}
}
class Yichang4
{
public static void main(String[] args)
{
Lizi a=new Lizi();
try
{
int daan= a.chufa(7,0);
System.out.println("除法结果是"+daan);
}
catch (Exception1 e)
{
System.out.println("除数为0");
System.out.println(e.toString());
}
System.out.println("Hello World!");
}
}
图9
图9的编译运行结果如图10所示
图10
Exception类和Error类都是Throwable类的子类,只有Throwable类这一体系才可以抛出。
————————————分割线————————
运行时异常一般可以不用在方法上声明(但是方法内部要用throw抛出异常对象)也不用使用try…catch…处理,但是编译通过运行不通过,虚拟机还是会报错。
————————————分割线——————————
异常中的覆盖情况:
子类覆盖父类,父类里面的方法抛出了异常,子类的覆盖方法只能抛出父类异常或者改异常的子类;如果父类方法抛出多个异常,子类覆盖方法只能抛出父类异常的子集;父类或者接口没有异常抛出,那么子类就算有异常也只能够内部解决,绝对不能够外抛。