异常详解.docx
- 文档编号:7476252
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:21
- 大小:21.85KB
异常详解.docx
《异常详解.docx》由会员分享,可在线阅读,更多相关《异常详解.docx(21页珍藏版)》请在冰豆网上搜索。
异常详解
异常详解
异常是什么呢?
异常就是程序在运行时出现不正常情况。
异常怎么由来的呢?
问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。
其实就是java对不正常情况描述后的对象体现。
对于问题的划分,总共两种:
a)严重的问题:
java通过Error类进行描述,对于Error一般不编写针对性的代码对其处理
b)非严重的问题,java通过Exception类进行描述,对于Exception可以使用针对性的处理方式进行处理
无论Error或者Exception都具有一些共性内容,比如不正常情况的信息,引发原因等。
这些共性的内容就Throwable,它是Error和Exception的父类
异常的处理
try-catch语句
对于异常我们怎么处理呢?
java提供了特有的语句(try-catch)进行处理。
格式如下:
try{
需要被检测的代码
}catch(异常类变量){
处理异常的代码;(处理方式)
}finally{
一定会执行语句;
}
蓝色部分可以省略不写
例如我们对以下代码除零抛出算数异常进行处理;
处理前:
classExceptionTest
{
publicstaticvoidmain(String[]args)
{
Demod=newDemo();
intx=d.div(3,0);
System.out.println(x);//抛出ArithmeticException异常
}
}
classDemo
{
publicintdiv(inta,intb){
returna/b;
}
处理后(使用try-catch):
classExceptionTest
{
publicstaticvoidmain(String[]args)
{
Demod=newDemo();
try{
intx=d.div(3,0);
System.out.println(x);//异常后,这段代码不执行
}catch(Exceptione){//Exceptione=newArithmeticException();
System.out.println("嗨,除零了");
}
}
}
classDemo
{
publicintdiv(inta,intb){
returna/b;
}
}
对于这个以上Exceptione其实是吧newArithmeticException();对象传给了形参e,就形成了多态。
Exceptione=newArithmeticException();对于catch捕获到的异常对象常见的方法操作是什么呢?
a)获取异常信息:
publicStringgetMessage():
返回此throwable的详细消息字符串
b)publicStringtoString():
返回此throwable的简短描述
c)publicvoidprintStackTrace():
将此throwable及其追踪输出至标准错误流。
对于这三种常见方法我们来看看如下代码:
classExceptionTest
{
publicstaticvoidmain(String[]args)
{
Demod=newDemo();
try{
intx=d.div(3,0);
System.out.println(x);
}catch(Exceptione){
System.out.println(e.getMessage());///byzero
System.out.println(e.toString());//异常名称:
异常信息
e.printStackTrace();//异常名称,异常信息,异常所出现的位置
//其实jvm默认的异常处理机制,就是在调用printStackTrace()方法,打印异常的堆栈的跟踪信息
}
}
}
classDemo
{
publicintdiv(inta,intb){
returna/b;
}
}
异常声明throws关键字
throws关键字在功能上通过throws的关键字声明了该功能有可能出现问题。
会提示你去如何让解决该功能如何解决?
不解决编译错误。
如以下代码:
classThrowsExceptionTest
{
publicstaticvoidmain(String[]args)
{
Demod=newDemo();
intx=d.div(3,0);
System.out.println(x);
}
}
classDemo
{
publicintdiv(inta,intb)throwsException{//编译抛出异常
returna/b;
}
怎么解决编译错误呢?
我们在main方法后面再加上)throwsException{编译没错,如果运行出错,最终虚拟机会处理,程序结束。
我们还是使用try-catch来处理这种异常,记住throws什么名称的异常,try-catch语句里就处理什么异常,如以下代码:
classDemo
{
publicintdiv(inta,intb)throwsArithmeticException{//抛出什么异常
returna/b;
}
}
classThrowsExceptionTest
{
publicstaticvoidmain(String[]args)
{
try{
Demod=newDemo();
intx=d.div(3,0);
System.out.println(x);
}catch(ArithmeticExceptione){//处理什么异常
System.out.println(e.toString());
}
}
}
多异常处理
我们在处理异常时,我们有如下建议:
a)声明异常时,建议声明更为具体的异常。
这样处理的可以更具体
b)catch里面应该有针对性的异常处理,不要把一切交给父异常Exception处理。
甚至不使用,出错了就停止程序,我们去处理程序。
为了代码的严谨性。
c)对方声明几个异常,就对应有几个catch块,如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面,不要定义多余的catch块。
d)建议在进行catch处理时,catch中一定要定义具体处理方式。
不要简单定义一句e.printSrackTrace(),也不要简单的就书写一条输出语句。
在实际开发中我们要对异常进行处理。
我们看看多异常处理的代码:
classDemo
{
publicintdiv(inta,intb)throwsArithmeticException,ArrayIndexOutOfBoundsException{
/*
数组越界异常
*/
int[]array=newint[a];
System.out.println(array[2]);
/*
除零异常
*/
returna/b;
}
}
classThrowsExceptionTest
{
publicstaticvoidmain(String[]args)
{
try{
Demod=newDemo();
intx=d.div(3,0);
System.out.println(x);
}catch(ArithmeticExceptione){
System.out.println(e.toString());//处理除零异常
System.out.println("除零了");
}catch(ArrayIndexOutOfBoundsExceptione){//处理数组越界异常
System.out.println(e.toString());
System.out.println("数组越界异常");
}catch(Exceptione){
System.out.println("otherException");//实际不建议使用,且不能放在catch块第一行
}
}
}
自定义异常
什么是自定义异常?
因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。
所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。
我们如何去自定义异常呢?
我们看一下以下程序的需求,在这段程序中,对与除数是-1,也视为是错误的是无法进行运算的。
那么就需要对这个问题进行自定义的描述。
classCustomException
{
publicstaticvoidmain(String[]args)
{
Divisord=newDivisor();
try{
intnum=d.divisor(4,-1);
System.out.println(num);
}catch(NegativeExceptione){
System.out.println(e.toString());
System.out.println("不能除以负数");
}
}
}
classDivisor
{
publicintdivisor(inta,intb)throwsNegativeException{//必须要抛出异常,否则编译错误
if(b<0){
thrownewNegativeException();//抛出自定义异常,使用throw
}
returna/b;
}
}
classNegativeExceptionextendsException//自定义除以负数异常
{
}
以上代码中,当在函数内部出现了throw关键字常对象,那么就必须要给对应的处理动作。
要么在函数上声明让调用者处理。
一般情况下,函数内出现异常,函数上需要声明。
我们发现打印的结果中没有只有异常的名称,却没有异常的信息,因为自定义的异常并未自定义信息。
如何自定义异常信息呢?
我们先看看如下代码?
classCustomException
{
publicstaticvoidmain(String[]args)
{
Divisord=newDivisor();
try{
intnum=d.divisor(4,-9);
System.out.println(num);
}catch(NegativeExceptione){
System.out.println(e.toString());
System.out.println("不能除以负数");
System.out.println("thisisnegative"+e.getValue());//调用自定义方法
}
}
}
classDivisor
{
publicintdivisor(inta,intb)throwsNegativeException{//必须要抛出异常,否则编译错误
if(b<0){
thrownewNegativeException("/bynagative",b);//抛出自定义异常,使用throw,
}
returna/b;
}
}
classNegativeExceptionextendsException//自定义除以负数异常
{
intvalue;//自定义一个值
NegativeException(Stringmsg,intvalue){//自定义构造方法
super(msg);//super调用父类中的构造方法
this.value=value;
}
publicintgetValue(){//子类自定义一个获取方法
returnvalue;
}
}
通过以上代码我们知道了如何自定义信息?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类,是通过super语句,那么就可以直接通过getMessage方法获取自定义的异常信息。
总结:
当我们自定义异常,必须是自定义类去继承Exception或者Throwable,Error。
为什么要继承Exception呢,异常体系中有一个特点,因为异常类和异常对象都需要被抛出,他们都具备可抛性。
这个可抛性是Throwable这个体系中独有的特点,只有这个体系中的类和对象才可以被throw和throws操作。
throws和throw的区别:
a)throws是使用方法上,throws后面跟的是异常类,可以跟多个,用逗号隔开
b)throw是使用在方法内,throw后跟的是异常对象。
RuntimeException
Exception中有一个特殊的子类异常RuntimeException运行时异常。
它和别的异常有种特殊的意义在里面。
a)如果在方法内容抛出该异常,方法上可以不用声明,编译也一样通过。
b)如果在方法上声明了该异常,调用者可以不用进行处理。
编译一样通过。
如以下例子:
classRuntimeExceptionTest
{
publicstaticvoidmain(String[]args)
{
Divisor2d=newDivisor2();
intnum=d.divisor(3,0);
System.out.println(num);
}
}
classDivisor2
{
publicintdivisor(inta,intb){
if(b==0){
thrownewArithmeticException("除零了");//ArithmeticException是RuntiemException的子类,如果是newException程序出错
}
returna/b;
}
}
注意:
我们之所以不用在方法上声明,是因为不需要让调用者处理。
当该异常发生,我们希望该程序去停止?
为什么呢?
因为在运行时,出现了无法继续运算的情况,希望停止程序后,让我们程序员对代码进行修正。
我们来看看自定义异常去继承RuntimeException是什么情况?
classRuntimeExceptionTest
{
publicstaticvoidmain(String[]args)
{
Divisor2d=newDivisor2();
intnum=d.divisor(3,-9);
System.out.println(num);
}
}
classDivisor2
{
publicintdivisor(inta,intb){//这里不用写throwsCustomsException2
if(b<0){
thrownewCustomsException2("除以负数啦");
}
if(b==0){
thrownewArithmeticException("除零了");//ArithmeticException是RuntiemException的子类
}
returna/b;
}
}
classCustomsException2extendsRuntimeException{//自定义异常去继承RuntimeException
Stringmsg;
CustomsException2(Stringmsg){
this.msg=msg;
}
}
从以上代码可以总结:
当我们自定义异常时,如果该异常的一旦发生,无法再继续进行运算,就让该自定义异常继承RuntimeException。
总结:
对于异常我们分为两种:
a)编译时被检测的异常
b)编译时不被检测的异常(运行时异常,RuntimeException以及其子类)
finally代码块
finally代码块是用来定义一个一定执行的代码块,通常用于关闭资源。
finally是一定会执行的
如以下例子:
classFinallyTest
{
publicstaticvoidmain(String[]args)
{
Demod=newDemo();
try{
intnum=d.method(4,0);
System.out.println(num);
}catch(Exceptione){
System.out.println(e.getMessage());
}finally{//这段代码一定会被执行
System.out.println("这段代码一定会被执行");
}
System.out.println("over");
}
}
classDemo
{
publicintmethod(inta,intb){
returna/b;
}
}
关于异常处理的格式总共有三种:
第一个格式:
try{
}catch(){
}
第二个格式:
try{
}catch(){
}finally{
}
第三个格式:
try{
}finally{
}
记住一点:
catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明。
异常-覆盖
异常在子父类覆盖中的体现:
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
如以下代码:
classFather//父类
{
publicvoidmethod()throwsFatherException{
}
}
classchildextendsFather//子类
{
publicvoidmethod()throwsChildException{//如果子类复写父类方法,必须抛父类已抛的异常
//或者是这个异常的子异常,不能抛其他异常。
也可以不抛异常
}
}
classFatherExceptionextendsException//父异常
{
}
classChildExceptionextendsFatherException//子异常
{
}
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集或者不抛异常
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类发生异常,就必须进行try处理,绝对不能抛。
异常的总结
异常是什么?
异常是对问题的描述。
将问题进行对象的封装
异常体系:
Throwable
|--Error
|--Exception
|--RuntimeException
异常体系中的特点:
异常体系中的所有类以及建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。
只有异常体系具备这个特点。
throw和throws的用法:
a)throw定义在方法内,用于抛出异常对象,当方法内容有throw抛出异常对象,并未被进行try处理,必须要在方法上声明,否则都是编译失败,注意,RuntimeException除外,也就是说,方法内如果抛出的RuntimeException异常,方法上可以不用声明。
如果方法声明了异常,调用者需要进行处理,处理方法可以throws可以try。
b)throws定义在方法上,用于抛出异常类,可以抛出多个,它们用逗号分隔开。
异常有两种:
a)编译是被检测异常。
该异常在编译时,如果没有处理(没有抛没有try),编译失败该异常被标识,代表这可以被处理
b)运行时异常(编译时不检测)。
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止,需要对代码进行修正
异常处理语句:
第一个格式:
try{
}catch(){
}
第二个格式:
try{
}catch(){
}finally{
}
第三个格式:
try{
}finally{
}
注意:
1.Finally中定义的通常是关闭资源代码,因为资源必须释放
2.finally只有一种情况不会执行。
当执行到Syetem.exit(0);finally不会执行。
自定义异常
定义类继承Exception或者RuntimeException
1.为了让该自定义类具备可抛性
2.让该类具备操作异常的共性方法
当药定义自定义异常的信息时,可以使用父类已经定义好的功能。
异常异常信息传递给父类的构造方法:
classMyExceptionextendsException
{
MyException(Stringmessage){
super(message);
}
}
自定义异常:
按照java的面向对象思想,将程序中出现的特有问题进行封装
异常的好处:
a)将问题进行封装
b)将正常流程代码和问题处理代码相分离,方便与阅读
异常的处理原则:
a)处理方式有两种:
try和throws
b)调用到抛出异常的功能是,抛出几个,就处理几个。
一个try对应多个catch。
c)多个catch,父类的catch放到最下面。
d)catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace,输出语句。
也不要不写
当捕获到的异常,本功能处理不了时,可以继续在catch中抛出
try{
thrownewAException
}catch(){
throwe
}
如果该异常处理不了,但并属于该功能出现的异常可以将异常转换后,在抛出和该功能相关的异常。
或者异常可以处理,当需要将异常产生的和本功能的相关的问题提供出去,当调用者知道,并处理,也可以将捕获异常处理后,转换新的异常
try{
thrownewAException();
}catch(AException){
//对AException先处理
thrownewBException();
}
比如说汇款的例子。
异常的注意事项:
在子父类覆盖时:
1.子类抛出的异常必须是父类的异常的子类或者子集
2.如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。
练习1:
毕老师上课:
classExceptionTest2
{
publicstati
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 异常 详解
![提示](https://static.bdocx.com/images/bang_tan.gif)