JAVA异常处理
异常:
是什么?是对问题的描述,见问题进行对象的封装
异常机制可以使程序中的异常处理代码和正常业务分离,保证程序代码更加优雅,并可以提高程序的健壮性。
1.异常基本概念
程序在运行时发生错误是不可避免的
在进行错误处理时,发现错误根据具体的情况可以划分为两大类
1.致命错误
不可恢复,例如内存泄露
2.非致命错误
读取一个文件,文件不存在
修改一个文件夹的名字,但是文件夹目前被使用
2.异常处理的思想
1.对于无法处理的错误,基于面向对象的思想,Java语言对其进行封装,成为一个对象,名字叫做Error,即不可恢复的错误
2.对于某些非致命性的错误,可以通过某种形式进行处理,Java语言对其进行封装,称为一个对象,名字叫做Exception,即可处理的异常现象
3.异常体系
异常体系:
异常体系的特点:1.异常体系中的所有类以及建立的对象都具备可抛性
Java的异常被分为两类:Checked ( 编译时异常 ) 异常和
Checked异常体现了java的设计哲学———没有完善错误处理的代码根本就不会被执行
对于Checked异常的处理方式有两种:
1.当前方法明确知道如何处理该异常,程序应该使用try...catch块来捕获该异常,然后在对应的catch块中修复该异常。
2.当前方法不知道如何处理该这种异常,应该在定义方法声明时抛出该异常。
Runtime异常则更加灵活,Runtime异常无需显式声明抛出,如果程序需要捕获Runtime异常,也可以用try...catch块来实现。
4.异常的分类
1.异常体系的分类非常庞大
2.常见的异常
NullPointException
IOException
SQLException
如果函数声明了异常,调用者需要进行处理,处理方式:
可以throws
1,编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
2,编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而或者引发
那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者
5.异常处理器
try…catch…finally(TCF结构)
如果执行try块里的业务逻辑代码时出现异常,系统会自动生成一个异常对象,该异常对象被提交给Java运行环境,这个过程被称为———抛出(throws)异常。
当java运行环境收到异常对象时,会寻找处理该异常对象的cathch块,如果找到合适的catch块,则把该异常对象交给该catch处理,这个过程被称为———捕获(catch)异常;如果java运行环境找不到捕获异常的代码块,则运行时环境终止,java程序也将退出。
注try块与if语句不一样,try块后的花括号({....})不可以省略,即使try块里只有一行代码,也不能省略这个花括号,与之类似的是,catch后的花括号也不能省略,还有一点需要指出:try块里声明的变量时代码块内局部变量,它只在try块内有效,在catch块内不能访问。
6.异常处理器——try
try语句块用于包裹可能引发异常的语句
try语句块中的语句不是一定会引发异常现象的
try语句块中的语句一旦引发异常,程序执行流程将自动跳转到对应的处理代码中,则从引发异常的语句向后直到try语句块结束大括号处的代码将不再运行
7.异常处理器——catch
catch语句块定义了针对try语句块中所引发的异常进行分门别类的处理
一个try语句块可以携带一个或多个catch语句块,但是只能引发其中任意一个处理方案,不可能执行一种以上的处理方法
catch语句块超过一个时,需要对其层次进行自上而下由小到大的层级排列,相互之间没有层级关系的语句可以随意排列顺序,不做要求
注catch是用于处理异常,如果没有catch就代表异常没有被
处理过,如果该异常是检测时异常,那么就必须声明。
8.异常处理器——finally
fianlly代码块:定义一定执行的代码,通常用于关闭资源
finally语句块定义了一段总是被运行的代码,无论try语句块中是否出现异常现象
finally语句块通常用于做现场清理的工作,例如try语句块中打开了一个文件,但是由于运行过程中出现了异常,转入到catch执行处理代码后,文件并没有被正常关闭,此时需要利用finally语句块来进行处理,将文件正常关闭
注Java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收对内存中对象所占用的内存。
注不要在finally块中使用如return或throw等导致方法终止的语句,一旦在finally块中使用了return或throw语句,将会导致try块,catch块中的return,throw语句失效。
9.异常处理器——catch与finally
异常处理器中的catch与finally可以共存,一个try语句可以携带一到多个catch语句块,但是只能携带一个finally语句块
异常处理器可以选择只携带catch语句块或finally语句块
异常处理流程代码也可以放在任何可能放可执行性代码的地方,因此完整的异常处理流程既可以放在try块里,也可以放在catch块,finally块里。
10.异常信息处理
catch语句块中针对出现的异常现象根据Java面向对象的原则,将出现的问题包装成一个对象,该对象中包含了异常现象对应的所有信息
异常对象名称
引发异常的原因
异常出现的位置(错误堆栈)
11.异常信息获取
catch语句块中针对出现的异常现象根据Java面向对象的原则,将出现的问题包装成一个对象,该对象中包含了异常现象对应的所有信息
1.异常对象名称
toString()
2.引发异常的原因
getMessage()
3.异常出现的位置(错误堆栈)
printStackTrace()
4.返回该异常的跟踪栈信息
getStackTrsce()
12.自定义异常
自定义异常即扩展Exception类,创建异常类对象
用户自定义异常都应该继承Exception基类,如果希望自定义Runtime异常,则应该继承RuntimeException基类。定义异常时通常需要提供两个构造器:一个是无参数的构造器;另一个是带一个字符串参数的构造器,这个字符串将作为该异常对象的描述信息(也就是异常对象的getMessage()方法的返回值)。
public class AuctionException extends Exception
{
}
13.异常对象抛出
自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。
1.针对某种异常现象可以指定抛出何种异常,在抛出异常时,使用throw指令抛出具体的异常对象
throw 异常对象
2.抛出异常对象后,JVM将检测抛出的异常是否被处理,此时可以通过下列两种形式来进行处理
对抛出的异常进行捕获
对抛出的异常不进行捕获,继续向上层调用者抛出
13.1使用throws声明抛出异常
使用throws声明抛出异常的思路是:当前方法不知道如何处理这种类型的异常,该异常该有上一级调用者处理;如果main方法也不知道该如何处理这种类型的异常,也可以使用throws抛出异常,该异常将交给JVM处理。JVM对异常的处理方法是:打印异常的跟踪栈信息,并终止程序运行,这就是前面程序在遇到异常后自动结束的原因。
Throws声明抛出只能在方法签名中使用,throws可以声明抛出多个异常类,多个异常类之间可以逗号隔开。Throws声明抛出的语法格式如下:
一旦使用了throws声明抛出该异常,程序就无须使用try...catch块来捕捉异常了。也就是说,调用该方法时,要么放在try块中显式捕获该异常,要么放在另一个带throws声明抛出的方法中,
public class ThrowsTest
{
}
Check异常的优势:——Check异常能在编译时提醒程序员代码可能存在的问题,提醒程序员必须处理该异常,或者声明该异常由该方法调用者来处理,从而可以避免程序员因为粗心而忘记处理该异常的错误。
13.2使用throw抛出异常
当程序出现错误时,系统会自行抛出异常;除此之外,Java也允许程序自行抛出异常,自行抛出异常使用throw语句来完成。
如果需要在程序中自行抛出异常,则应使用throws语句,throw语句可以单独使用,throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例,语法格式如下:
throw ExceptionInstance
13.3throws和throw的用法
throw定义在函数内,用于抛出异常对象
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开
当函数内有throw抛出异常对象,并未进行try处理,必须在函数上声明,
否则都将编译失败。
注意:RuntimeException除外,也就是说,函数内如果抛出的是RuntimeException
异常,函数上可以不用声明。
14.方法抛出异常
1.方法抛出异常是对方法的定义进行声明,明确方法执行过程中可能引发异常现象,提醒调用者要对其进行处理
2.方法抛出异常要求调用者强制处理,除非抛出的异常为RuntimeException的子类,否则必须对其进行处理。可以利用此特点,设计自定义异常类的对象
15.异常处理的应用
1.异常现象在编程过程中及其常见,在开发过程中,如果调用了可能引发异常的语句,最常见的处理方案是针对对应的语句使用tcf结构对其进行处理,并打印错误的异常堆栈信息,然后针对错误信息进行分析,制作对应的异常处理方案
2.在开发调试期间,打印的异常信息可以作为编程人员的参考性信息,但是在实际运行期间,此类信息必须要屏蔽掉,以更友好的形式展示给最终用户
16.异常在子父类覆盖中的体现
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2.如果父类方法抛出多个异常,子类在覆盖该方法时,子类只能抛出父类异常的子集
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常,如果子类方法发生了异常,就必须进行try处理,绝对不能抛。
*/
Exception
*/
//定义了3个异常类
class AException extends Exception{
}
class BException extends AException{
}
class CException extends AException{
}
//父类抛出A异常
class Fu{
}
class Test{
}
//子类只能抛出A异常或者B异常
class Zi extends Fu{
}
17.异常的处理原则
异常的注意事项:
18.异常相关面试
针对finally语句块的执行特点,如果在finally语句块中添加了return语句,则执行到此处时,会对整体方法的返回值进行修改。