8异常及其处理知识点文档格式.docx
- 文档编号:432384
- 上传时间:2023-04-28
- 格式:DOCX
- 页数:16
- 大小:126.84KB
8异常及其处理知识点文档格式.docx
《8异常及其处理知识点文档格式.docx》由会员分享,可在线阅读,更多相关《8异常及其处理知识点文档格式.docx(16页珍藏版)》请在冰点文库上搜索。
StringgetLocalizedMessage()
voidprintStackTrace()
ThrowablefillInStackTrace()
四.throws子句---方法定义的完整语法。
1.语法.
方法修饰符结果类型方法名(形参表)throws子句方法体
throws子句的语法是
throws异常类型名1,……,异常类型名n
其中throws是java保留字,诸异常类型名是检查型异常的名字。
2.对方法体的限制.
方法体中抛出的任何检查型异常,无论是由throw语句抛出的还是由于调用其它方法而发生的检查型异常,其类型都必须是throws子句中列出的某个类型或其子类型。
否则编译期间出错。
因此,编译器能够保证:
通过编译的程序中的所有检查型异常都得到了处理。
3.对方法重写的限制.
子类重写方法f,那么子类的f不能抛出比基类f更多的检查型异常。
但是允许重写的f抛出较少的检查型异常,甚至不抛出任何检查型异常。
重写子类方法时,如果允许子类方法抛出比基类方法更多的异常,那么将破坏“通过编译的程序中的所有检查型异常都得到了处理”这一事实。
异常及其处理.
在运行过程中,应用程序可能遇到各种错误。
例如,从一个已经关闭的流读数据;
访问数组时数组下标越界;
使用空引用调用方法等。
许多程序员不检查可能的错误,理由是如果每执行一个语句都检查是否出错,将使程序的结构混乱,难以理解。
为了解决程序的正确性和程序结构的清晰性之间的矛盾,程序设计语言引入了异常及异常处理机制。
下面是java语言的异常处理机制的粗略过程:
1.程序运行时出错,抛出异常对象.当程序执行过程中出现错误(例如0做除数,数组下标越界等)时,系统会自动创建一个对象(称作异常对象,包含出错信息)并且抛出这个对象,或者在程序执行期间遇到无法继续执行的情况(例如打开文件失败,连接数据库失败等),程序员可以创建一个异常对象,然后使用throw语句抛出这个异常对象。
2.终止程序的正常执行顺序,转去查找处理该异常的代码.只要有异常对象E被抛出(无论是由系统抛出的还是由throw语句抛出的),程序就立即停止正常的执行顺序,转去查找处理异常对象E的代码。
查找策略是首先在当前方法中查找,没有找到则本方法结束,到调用该方法的方法中继续查找,如果一直查找到main方法也没有找到处理该异常的代码,打印堆栈踪迹后程序结束。
3.处理异常.如果在调用链的某个方法中找到处理这个异常的代码,则执行这段代码以及之后的代码。
与异常处理有关的语句是throw语句,try-catch-finally语句和Throwable类及其子类。
二.与异常处理有关的语句
1.throw语句
语法:
throwexpression;
这里throw是保留字,expression是一个表达式,它的值一定是某个Throwable类对象的引用。
throw语句的功能是:
计算表达式得到一个Throwable对象的引用e,抛出e使得系统进入异常处理状态,查找处理该类异常的catch子句。
如果找到这样的catch子句,系统恢复到正常执行程序的状态,开始处理异常;
如果一直找不到处理该类异常的catch子句,线程终止。
例.看下面代码段
//创建Throwable对象,系统并不进入异常处理状态
Throwablee=newThrowable();
……//其它代码,系统正常执行这些代码
if(B)throwe;
//抛出异常,系统进入异常处理状态,查找处理e的代码。
else
……//系统仍旧处于正常执行程序的状态,执行这些代码。
2.try-catch-finally语句
语法1:
try
{statements}//{…}称作try块
catch(Exception类型1e1){statements_1}//{…}称作catch块
……
catch(Exception类型nen){statements_n}//{…}称作catch块
语法2:
catch(Exception类型nen){statements_n}//{…}称作catch块
finally{statements}//{…}称作finally块
这里try,catch,finally都是java语言的保留字。
e1,e2,…,en是标识符。
要特别注意,诸catch子句的异常类型应该子类型在前,父类型在后,否则编译出错。
因为父类型的catch会拦截子类型的异常对象,使子类型的catch永远也不会起作用,成为不可抵达的代码。
例.
packagetest_try;
classMyErrorextendsError
{//定义一个Error的子类
MyError(){}
MyError(Strings){super(s);
}
publicclasstest_try
{
staticvoidthrow_Error()
{
//定义方法,它抛出Error或Exception
thrownewMyError("
zzzz"
);
//thrownewNullPointerException();
}
publicstaticvoidmain(String[]args)
{
try{
throw_Error();
//调用抛出异常的方法
catch(NullPointerExceptione)
{//捕获并处理异常
System.out.println("
NullPointerException"
catch(Exceptione)
System.out.println("
Exception"
finally{//finally块
Executingfinallyblock."
第一个throw语句起作用时,程序的输出。
由于MyError继承自Error,因此两个catch子句都不能捕获这个异常。
test_try.MyError:
zzzz//异常没被捕获。
调用uncaughtException()方法,输出堆栈踪迹。
attest_try.test_try.throwError(test_try.java:
8)
attest_try.test_try.main(test_try.java:
13)
Executingfinallyblock.//此输出表明finally块一定执行。
Exceptioninthread"
main"
第二个throw语句起作用时程序的输出。
这时异常得到处理,因此不会输出堆栈踪迹。
processingNullPointerException
Executingfinallyblock.
三.异常类
Throwable
是所有异常类的超类。
它只有两个子类Error和Exception。
Error类
及其子类表示程序具有严重的错误,例如VirtualMachineError就是Error的一个子类。
Exception类
表示程序的某种状态,该状态是应用程序希望捕获的。
Exception类有为数众多的子类,像
IOException,
SQLException,
NoSuchFieldException,
NoSuchMethodException
RuntimeException
等等。
其中RuntimeException是Exception的重要子类,它也有许多子类,像
ArithmeticException
ClassCastException
NegativeArraySizeException
NullPointerException
IndexOutOfBoundsException
检查型异常.Exception的子类,但不是RuntimeException或其子类的所有异常类型统称为检查型异常(checkingexception);
其它异常类型,即Error及其子类型和RuntimeException及其子类型统称为非检查型异常(uncheckingexception)。
关于检查型异常这一名称的来源,见方法定义中的throws子句。
Throwable类及其子类都是具体类,并且绝大多数类仅仅是名称不同,所具有的方法都是继承自Throwable类。
Throwable类
publicclassThrowableextendsObjectimplementsSerializable
Throwable类是所有errors和exceptions的超类。
只有该类及其子类的对象可由JavaVirtualMachine或throw语句抛出。
也只有该类及其子类可以做catch子句的参数类型.
Throwable类的实例用于指出异常情况已经出现,并且包含异常情况的相关信息。
通常throwable类有两个构造函数:
一个无参数的构造函数,一个带一个String型参数msg的构造函数,参数msg给出异常情况的详细信息。
Throwable类的对象包含两类信息:
1.关于异常情况的信息(一个串)。
2.异常情况出现时执行堆栈的状态。
构造一个Throwable对象,具有空错误消息的。
构造一个Throwable对象,其错误消息是message。
返回当前Throwable对象的错误消息。
创建Throwable类的更具专用色彩的描述信息。
继承Throwable类的子类应该重写该方法,Throwable类的getLocalizedMessage()与getMessage()功能相同。
打印该Throwable对象的错误信息,并打印执行堆栈信息到标准错误流。
具体打印形式与实现有关。
java.lang.NullPointerException第一行是e.toString()方法的结果,以下是堆栈信息
atMyClass.M2(MyClass.java:
9)发生异常的语句所在方法名,文件名,行号
atMyClass.M1(MyClass.java:
6)调用前一方法的方法名,文件名,行号
atMyClass.main(MyClass.java:
3)以后同上
这个例子由运行如下程序产生
1.classMyClass{
2.publicstaticvoidmain(String[]argv){
3.M1(null);
4.}
5.staticvoidM1(int[]a){
6.M2(a);
7.}
8.staticvoidM2(int[]b){
9.System.out.println(b[0]);
10.}
11.}
把当前对象加入执行堆栈踪迹,返回当前对象作为值。
常用于重新抛出异常。
1packagetest_exception;
2publicclasstest_exception{
3publicstaticvoidmain(String[]args)
4{
5f1();
6}
7staticvoidf1(){
8f2();
9}
10staticvoidf2(){
11try{
12thrownewNullPointerException("
aaaa"
13}
14catch(NullPointerExceptione)
15{
16e.printStackTrace();
17NullPointerException
e1=(NullPointerException)e.fillInStackTrace();
18System.out.println(e==e1);
19e.printStackTrace();
20throw(NullPointerException)e.fillInStackTrace();
java.lang.NullPointerException:
aaaa//由第16行的printStackTrace()打印
atmy_1.my_1_main.f2(test_exception.java:
12)
atmy_1.my_1_main.f1(test_exception.java:
atmy_1.my_1_main.main(test_exception.java:
5)
aaaa//由第19行的printStackTrace()打印
atmy_1.my_1_main.f2(test_exceptionmy_1_main.java:
17)
atmy_1.my_1_main.f1(test_exceptionmy_1_main.java:
atmy_1.my_1_main.main(test_exceptionmy_1_main.java:
aaaa//由第20行的throw引起
20)
true//由第18行输出,表明e.printStackTrace()返回的就是e。
四.throws子句---方法定义的完整语法
以前介绍的方法定义的语法是
方法修饰符结果类型方法名(形参表)方法体
方法定义的完整语法是
这里新增加的语法成分是throws子句,它的语法是
throws异常类型名1,……,异常类型名n
其中throws是java保留字,诸异常类型名是检查型异常的名字(可以填写非检查型异常名,但它不会起任何作用)。
对方法体的限制.
这意味着如果方法f的throws子句是throwsE1,…,Em,那么
如果f的方法体中有thrownewE(“…”)形式的语句,其中E是检查型异常,那么E是E1,…,Em中的一个,或者是E1,…,Em中某一个的子类。
如果方法f调用方法g,那么g的throws子句中的每个检查型异常都必须是E1,…,Em之一或者是某个Ek的子类。
否则要么方法f处理这个异常,要么编译时出错。
并不要求方法f必须抛出throws子句列出的所有异常,而是说f只能抛出throws子句列出的检查型异常。
这就命名这类异常为“检查型异常”的原因。
对方法重写的限制.
假设方法f()throwsE1,…,Em{…}是基类的一个方法。
如果子类需要重写方法f,那么f不能抛出比基类f更多类型的检查型异常,它只能抛出Ek或Ek的子类型的异常。
但是允许重写的f抛出较少的检查型异常,甚至不抛出异常。
例.这个例子说明,一个方法抛出的检查型异常必须是出现在throws子句中列出的异常。
publicclasstest_checkedexception
voidg()throwsNoSuchMethodException,NoSuchFieldException
……//抛出两种检查型异常
voidf()throwsNoSuchMethodException
{
thrownewNoSuchFieldException();
//编译出错,throw语句抛出的检查型异常
//不在throws子句中
g();
//编译出错,方法调用g()抛出的检查型异常不在throws子句中
voidf1()throwsNoSuchMethodException
{//虽然throw语句抛出了throws子句之外的检查型异常,但f1处理了该异常,正确。
try
catch(NoSuchFieldExceptione){}
voidf2()throwsNoSuchMethodException
{//虽然g()抛出了throws子句之外的检查型异常,但f2处理了该异常,正确。
{
下面的例子说明,重写的方法不能抛出更多的异常,但可以抛出较少的异常,甚至不抛出异常。
classtest_inheritextendstest_checkedexception
voidf1()throwsNoSuchMethodException,NoSuchFieldException
//编译出错.重写的f1比基类的f1抛出更多的检查型异常。
voidf2()
//编译通过.允许重写的方法比基类方法抛出更少的检查型异常,
//甚至不抛出检查型异常。
习题.
1.重写子类方法时,如果允许子类方法抛出比基类方法更多的异常,那么将破坏“通过编译的程序中的所有检查型异常都得到了处理”这一事实。
为什么?
提示:
方法g调用方法f,方法f至少有本类和基类两个版本。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 异常 及其 处理 知识点