




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
4.4 异常4.4.1 了解异常异常定义了程序中遇到的非致命的错误, 而不是编译时的语法错误,如程序要打开一个不存的文件、网络连接中断、操作数越界、装载一个不存在的类等。 我们先来看看下面的程序代码吧:public class TestExceptionpublic static void main(String args)int result = new Test().devide( 3, 0 );System.out.println(“the result is” + result );class Testpublic int devide(int x, int y)int result = x/y;return result;编译运行上面的程序,将出现如下错误:Exception in thread main java.lang.ArithmeticException: / by zero at Test.devide(TestException.java:14) at TestException.main(TestException.java:5) 上面的程序运行的结果报告发生了算术异常(ArithMethicException),系统不再执行下去,提前结束,这种情况就是我们所说的异常。4.4.2 try catch语句我们将上面的程序代码进行如下修改:public class TestExceptionpublic static void main(String args)tryint reslut = new Test().devide( 3, 0 );System.out.println(the result is + reslut );catch(Exception e)System.out.println(e.getMessage();System.out.println(program is running here ,that is normal !);class Testpublic int devide(int x, int y)int result = x/y;return result;程序运行结果如下:/ by zeroprogram is running here ,that is normal !我们看到程序在出现异常后,系统能够正常的继续运行,而没有异常终止。在上面的程序代码中,我们对可能会出现错误的代码用trycatch语句进行了处理,当try代码块中的语句发生了异常,程序就会跳转到catch代码块中执行,执行完catch代码块中的程序代码后,系统会继续执行catch代码块后的其他代码,但不会执行try代码块中发生异常语句后的代码,如程序中的System.out.println(“the result is” + result ); 不会再被执行。可见Java的异常处理是结构化的,不会因为一个异常影响整个程序的执行。当try代码块中的程序发生了异常,系统将这个异常发生的代码行号,类别等信息封装到一个对象中,并将这个对象传递给catch代码块,所以我们看到catch代码块是以下面的格式出现的。catch(Exception e) System.out.println(e.getMessage();catch关键字后跟有一个用括号括起来的Exception类型的参数e,这跟我们经常用到的如何定义一个函数接收的参数格式是一样的。括号中的Exception就是try代码块传递给catch代码块的变量类型,e就是变量名,所以我们也可以将e改用成别的名称(如ex等),如下所示:catch(Exception ex)System.out.println(ex.getMessage();4.4.3 throws关键字针对上面的例子,我们假设TestException类与Test类不是同一个人写的,写TestExc- ption类的人,在main方法中调用Test类的devide方法时,怎么能知道devide方法有可能出现异常情况呢?他又怎么能够想到要用try catch语句去处理可能发生的异常呢?问题可以这样解决,只要写Test类的人,在定义devide方法时,在devide方法参数列表后用throws关键字声明一下,该函数有可能发生异常及异常的类别。这样,调用者在调用该方法时,就必须用trycatch语句进行处理,否则,编译将无法通过。如下面的程序代码:public class TestExceptionpublic static void main(String args)int result = new Test().devide( 3, 1 );System.out.println(“the result is” + result );class Test public int devide(int x, int y) throws Exceptionint result = x/y;return x/y;编译上面的程序,将出现如下的编译错误。TestException.java:5: unreported exception java.lang.Exception; must be caught or declared to be thrown int result = new Test().devide( 3, 1 ); 1 error读者应注意一下出错的行号,就能够发现错误的位置。尽管我们已经将传给devide函数中的第二个参数改为了1,程序在运行时不可能发生错误,但由于定义devide函数时声明了它有可能发生异常,调用者就必须使用trycatch语句进行处理,这叫防患于未然。将程序作如下修改:public class TestExceptionpublic static void main(String args)tryint result = new Test().devide( 3, 1 );System.out.println(“the result is” + result );catch(Exception e)e.printStackTrace();/很多人为了简单,不写这一句。编译上面的程序,没有任何问题了。小经验:很多人确信自己的程序中不会发生某种异常,trycatch语句似乎成了应对编译器而不得已的手段,为了简单,他们往往在catch代码块中什么也不写,就象上面标注的那样。trycatch成了一种摆设。作者强烈要求读者养成良好的编程习惯,不要回避这一点辛劳,贪图这么一点时间。在catch代码块中,最好有处理异常的代码,否则,一旦程序在运行过程中出现了异常,导致最终运行结果与我们期望的不一致,我们就很难发现问题的原因了。throws关键字的其他用处如果一个方法中的语句执行时可能生成某种异常,但是并不能确定如何处理,则此方法应声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。也就是,程序中异常没有用trycatch捕捉异常、处理异常的代码,我们可以在程序代码所在的函数(方法)声明后用throws声明该函数要抛出异常,将该异常抛出到该函数的调用函数中,一直到main方法,JVM肯定要处理的,这样,编译就能通过了。用作者的话讲,就是将麻烦传递给了上级,村长传给乡长,乡长不处理就传给县长,县长不处理又传给市长,最后一直传到国务院,就截止了,因为国务院没有上级了。在Java程序中, 异常传递到main方法后,就截止了,因为没有哪个方法会调用main方法的。如上面的程序就可以改写成下面这样:public class TestExceptionpublic static void main(String args) throws Exceptionint result = new Test().devide( 3, 1 );System.out.println(“the result is” + result );虽然编译能够通过,但异常一旦发生,没有被处理,程序就会非正常终止。即使你能确信在你的程序中不会发生某种异常,这种方法也能够简化程序的编写,但完全违背了Java设计异常的初衷,不建议在正规的程序中使用。用这种方法写点实验性的代码,倒是无可厚非。4.4.4 自定义异常与Throw关键字我们通过查阅JDK文档资料,就能看到,Exception类是java.lang.Throwable类的子类,Exception类继承了Throwable类的所有方法。其实,我们在实际应用中,是使用Exception的子类来描述任何特定的异常的。Exception类是所有异常类的父类,Java语言为我们提供了许多Exception类子类,分别对应不同的异常类型,如我们在前面已经看到过以下几个异常。l ArithmeticException(在算术运算中发生的异常,如除以零)l NullPointerException(变量还没有指向一个对象,就引用这个对象的成员)l ArrayIndexOutOfBoundsException(访问数组对象中不存在的元素)除了系统提供的异常,我们也可以定义自己的异常类,自定义的异常类必须继承Exception类。假设我们在上面程序的devide函数中,不允许有负的被除数,当devide函数接收到一个负的被除数时,程序返回一个自定义的异常(这里就叫负数异常吧!)通知调用者。我们可以这样定义这个负数异常类。class DevideByMinusException extends Exceptionint devisor;public DevideByMinusException(String msg,int devisor)super(msg);this.devisor = devisor;public int getDevisor()return devisor;Java是通过throw关键字抛出异常对象的,其语法格式是throw 异常对象;如果我们的程序想跳转,我们可以抓住自己抛出的异常。否则,则此方法应声明抛出异常,而由该方法的调用者负责处理。如果我们要在devide函数接收到的第二个参数(也就是被除数)为负数时,向调用者抛出自定义的DevideByMinusException对象,程序代码如下:class Testpublic int devide(int x, int y) throws ArithmeticException, DevideByMinusExceptionif(y 0)throw new DevideByMinusException(“被除数为负”,y); /这里抛出的异常对象,就是调用者在catch(Exception e)语句中接收的变量e。int result = x/y;return x/y;我们能够看到,上面的代码中,devide方法声明时抛出了两个异常。java中一个方法是可以被声明成抛出多个异常的。下面再来看看调用程序应该如何对devide方法中的多个异常作出处理。public class TestExceptionpublic static void main(String args)tryint result = new Test().devide( 3, 0 );/int result = new Test().devide( 3, -1 );/int result = new Test().devide( 3, 1 );System.out.println(“the result is ” + result );catch(DevideByMinusException e)System.out.println(“program is running into”+ “DevideByMinusException”);System.out.println(e.getMessage();System.out.println(“the devisor is ” + e. getDevisor();catch(ArithmeticException e)System.out.println(“program is running into”+ “DevideByMinusException”);System.out.println(e.getMessage();catch(Exception e)System.out.println(“program is running into”+ “other unknowned Exception”);System.out.println(e.getMessage();System.out.println(“program is running here ,that is normal !”);上面的程序使用一个try后面跟着多个 catch来捕捉异常,每一个catch可以处理一个不同的异常类型。如果我们调用devide(3,0),将发生ArithmeticException异常,程序将跳转至catch(ArithMeticException e)代码块中执行。如果我们调用devide(3,-1),将发生DevideByMinusException异常,程序将跳转至catch(DevideByMinusException e)代码块中执行。如果在devide方法中发生了ArithmeticException、DevideByMinusException之外的任何其他异常,程序将跳转至catch(Exception e)代码块中执行,也就是还没有由前面的catch处理的异常,都将由catch(Exception e)代码块处理,不是因为该语句是最后一个catch,而是由于Exception是所有异常类的父类,从语法上来讲,是能够处理所有异常的。所以,各种catch代码块的放置顺序非常重要,catch(Exception e)不能放在其他catch语句的前面,否则后面的catch永远得不到执行,就没有什么意义了。大家可以用if ,else if,else if,else结构去考虑try.catch问题。读者可以逐一去掉程序中被注释的devide语句的注释符,注释掉其他的devide语句,对比观察运行结果。&多学两招:我们可以在一个方法中使用throw,trycatch语句来实现程序的跳转,下面是描述这种方法的一段简要程序代码:void fun()tryif(x=0)throw new YyyException(“Yyy”);/跳转到代码块1处else(x=1)throw new XxxException(“Xxx”); /跳转到代码块2处catch(YyyException e)代码块1catch(XxxException e)代码块24.4.5 finally关键字在trycatch语句后,我们还可以有个finally语句,finally语句中的代码块不管异常是否被捕获总是要被执行的。我们将上面的程序作如下修改,来看看finally语句的用法与作用。public class TestExceptionpublic static void main(String args)tryint reslut = new Test().devide( 3, 0 );/int reslut = new Test().devide( 3, -1 );/int reslut = new Test().devide( 3, 1 );System.out.println(“the result is” + result );/return ;catch(DevideByMinusException e)System.out.println(“program is running into”+ “DevideByMinusException”);System.out.println(e.getMessage();System.out.println(“the devisor is ” + e. getDevisor();System.exit(0);catch(ArithMeticException e)System.out.println(“program is running into”+ “DevideByMinusException”);System.out.println(e.getMessage();return ;catch(Exception e)System.out.println(“program is running into”+ “other unknowned Exception”);System.out.println(e.getMessage();finallySystem.out.println(“program is running into finally”);System.out.println(“program is running here ,that is normal !”);爱思考的读者也许会问:程序中的最后一句System.out.println(“program is running here ,that is normal !”);不论有没有异常发生,该语句都会执行,那何必还用finally语句呢?finally还是有其特殊之处的,即使try代码块和catch代码块中使用了return语句退出当前方法或break跳出某个循环 ,相关的finally代码块都要执行,读者可以逐一去掉程序中被注释的devide语句的注释符,注释掉其他的devide语句,对比观察运行结果。finally中的代码块不能被执行的唯一情况是:在被保护代码块中执行了System.exit(0)。每个try语句必须有一个或多个catch语句对应,try代码块与catch代码块及finally代码块之间不能有其他语句。如下面的代码是非法的。tryx = 3 + 5;/代码位置是非法的catch(Exception e)4.4.6
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建筑工程设计优化及技术咨询服务合同
- 观革命电影有感450字14篇
- 直接引语和间接引语的转换技巧:初中英语课程教案
- 纪检委员培训课件
- 人教版八年级英语上册Unit 5完形填空专题复习练习题(含答案解析)
- 唐诗三百首鉴赏与实践教学方案
- 工业园区招商合同
- 早教课件在家听
- 企业间知识产权保护与交易合作合同
- 纪念塔课件教学课件
- 2025-2026学年人教PEP版(2024)小学英语四年级上册教学计划及进度表
- 血管外科常用药物
- 消防桌面应急预案方案(3篇)
- 山区救援网2025年灾害救援装备研发趋势分析报告
- (2025年标准)校车修理协议书
- 2025-2030中国光耦元件市场竞争风险及发展态势分析报告
- 服装厂 安全生产管理制度
- 2025年中州水务财务笔试题及答案
- 2025年山东省教育厅直属事业单位招聘18人笔试模拟试题带答案详解
- 2025年中小学体育教师招聘考试专业基础知识考试题库及答案(共2687题)
- 脊髓损伤的康复课件
评论
0/150
提交评论