当前位置:高等教育资讯网  >  中国高校课件下载中心  >  大学文库  >  浏览文档

《Thinking in Java》中文版 第九章 用异常来处理错误

资源类别:文库,文档格式:PDF,文档页数:41,文件大小:468.67KB,团购合买
Java的基本哲学是“糟糕的代码根本就得不到执行”。 捕捉错误的最佳时机应该是在编译的时候,也就是程序能运行之前。但 是,不是所有的错误都能在编译的时候被发现。有些问题只能到程序运行 的时候才能得到处理。它们要通过某种方式,让引发问题的代码将适当的 信息传给那些知道该怎样正确处理这些问题的程序。
点击下载完整版文档(PDF)

Thinking in Java 3 Edition 9:用异常来处理错误 Java的基本哲学是“糟糕的代码根本就得不到执行”。 捕捉错误的最佳时机应该是在编译的时候,也就是程序能运行之前。但 是,不是所有的错误都能在编译的时候被发现。有些问题只能到程序运行 的时候才能得到处理。它们要通过某种方式,让引发问题的代码将适当的 信息传给那些知道该怎样正确处理这些问题的程序。 C以及其它早期语言通常都有多个错误处理的方案,一般来说它们都是建 立在约定的基础上的,其本身并不属于语言。最常见的做法是,返回一个 特殊的值或设定一个标志,然后希望接收方会看到这个值或标记,并以此 判断是不是出了什么问题。但是,随着时间的推移,人们发现,那些使用 着类库的程序员们通常都认为自己是刀枪不入的——他们的心态可以归纳 为“错误,那时别人的事,我的代码绝不可能有错。”所以,也就不奇怪 他们为什么不检查错误条件了(况且有些错误也实在是蠢了点40,以至于 你都想不到还要去检查)。而且,如果你真的每次调用方法的时候,都作 遍完整的错误检査的话,那代码也就没法读了。由于程序员们还能用这 些语言凑出一些系统,因此他们一直拒绝承认这样一个事实:这种错误处 理的方法已经成为创建大型的、强壮的、可维护的程序的巨大障碍了。 解决的方案就是,强化错误处理的规范性屏弃其原有的随意性。实际上, 这种做法已经有很长的历史了。因为异常处理( exception handling)的 实现最早可以追溯到1960年代的操作系统,甚至是 BASIC的“on error goto”。不过C++的异常处理源于Ada,而Java的则主要建立 在C++的基础之上(尽管看上去更像 Object Pascal的)。 exception”这个词的意思有“我对此表示反对”的意味。问题发生的 时候,可能你不知道该如何处理,但是你知道不能再没心没肺的运行下去 了;你必须停下来,自然会有人知道该如何处理,而处理方案也应该藏在 什么地方。但是在现有的条件下,你还不知道问题的详细情况,因此没法 解决这个问题。所以你应该把问题交上去,那里会有人来作决定的(就像 是行政命令,一级管一级) 异常还有一个非常重要的好处,就是让错误处理代码显得更有条理。与原 先“程序要在多个地方检査同一个错误,并就地作处理”相比,现在,你 无需再在方法调用的时候作检査了(因为异常肯定能被捕获)。而且处理问 题的代码也集中到一个被称作“异常处理程序( exception handler)”地 方了。这种做法能为你省下不少代码,而且还把“讲述要作什么的代 码”,同“出错的时候该执行的代码”分开来了。总之,无论是写代码还 是调试程序,使用异常都比用老式的错误处理更有条理。 第1页共2页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Thinking in Java 3 rd Edition ￾ 1 ✁ ✂ 2 ✁ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com 9: Java     !"#$ %&'()*+ #,-.' !"/01-2345'%&( "6'789:;?@A#BC034 DEF GHIJK2LMNOPQ78R234%& C STU9VWXY<Z.-[\78@]#^_`a9:.b cdefg#UhijkXYZlmn#op^\ qrstue^\vw#xyz{|}@~R\stv€#iS ‚ƒ„…†‡34+#ˆ‰Š‹Œ#:01#K2Ž ‰‘%&’:<Z.•™šš›:œžSŸ  #K¡¢#£ ¤ž'-,S#$ ¥¦ ›:†‡§¨©ª…(«¬-2$­®…¯ ✄☎ ✆ ✝ #S°k ±.²³;´§¨)µ¬#¶·±¸¹º@n"#.» ^¼½¾§¨¿#K $ ÀnÁ…Âk%&’:³'R 2XYÄ^2ÄÅ#Ɓ›:^ÇȤÉRO^\¢­ÊR?7 8@nËÌÍÎbÏÐÑ ÒÓÑ žÔÕ%&ÖÏ×؅ ÙÚ@] #ÒÛ78ÜÝÞßàUá-ˆâÞ­ãg# R?mnËÌ-äåæç…ÆèZ78(exception handling) ­1VžSéê 1 960 ë ì»ÄÅ#í° BASIC on error goto= C+ + èZ78îk Ada#µ Java ïð;bc  C+ + f)g(ñòg´óô Ob ject Pascal) excep ti on R\õâö-£÷øùú÷âû340ü "#ž'±LM¶ý78#+±LM'þÀœÀ(´ … ±`#•x~-LM¶ý78#µ78@]$ †‡@+1-©ª#±³LM34 «#ƁÀn ÙÚR\34,S± 34 g´#K~-`»Úe( ô #^ò^ ) èZ³-^\Z;7# B78 ó-©8á %&;[\@§¨^\#i »78#1#± þ@nº"»§¨…(ÆèZe'/)µ¬783 4 $ !^\/"»èZ78%&(exception handler) @…R?mn'±#$ #µ¬³ %&;»†‡ #„" '(`…))#*+ ³ º,%&#ŽèZ.-A78ó-©8

hapter 9: Error Handl 由于“异常处理”是Java唯一的正式报告错误的方式,而且Java编译 器还对此作了强制要求,因此即使不学异常处理,也可以写出很多本书中 的例程。本章会介绍如何正确地处理异常以及,如何定义你自己的异常 以供方法出问题的时候使用。 基本异常 “异常条件( exceptional/ condition)”是一种能阻止正在运行的方法或 其某一部分继续运行下去的问题。把异常条件同普通问题区分开来,这点 很重要。遇到普通问题的时候,你在当前的运行环境下有足够的信息来处 理这个困难。对于异常条件,由于你得不到足够的用以处理这个问题的信 息,因此不能在“当前的运行环境下( in the current context)”继续运 行下去。你只能跳出当前的运行环境,并且把问题交到上层的运行环境。 这就是抛出异常的时所发生的事情。 除法就是一个例子。如果知道会除以零的话,还是应该去测试一下的。但 是被除数是零又代表什么呢?或许你知道。你可以根据问题的上下文,决 定如何处理零作分母的情况。但是如果这不是一个预料中的值,因此你不 知道该如何处理的话,那就必须抛出一个异常,而不是顺着执行的路径继 续下去了。 当你抛出异常的时候,有几件事会随之发生。首先要像创建其它Java对 象那样,创建一个异常对象:在堆里,用new。然后停下当前的执行路 径(这条路是不能再继续下去了),再将异常对象的 reference从当前运行 环境当中弹岀去。现在异常处理机制开始接管程序了,它会去找到一个合 适的地方来继续执行这个程序。这个地方就是“异常处理程序 ( exception handler)”,其功能就是将程序从问题中恢复过来,于是程 序或者是尝试去换一条运行路径,或者是继续运行下去。 举一个抛异常的简单例子,看看t这个 reference。它可能还没有经过初 始化,因此你应该先检查一下再用它去调用方法。你可以创建一个表示错 误信息的对象,并把这个对象“抛出”当前的运行环境,这样就能把出错 的信息传递到更高层的运行环境中了。这被称为“抛出一个异常 ( throwing an exception)。”就像这里看到的: if(t throw new NullPointerException () 这样就抛出了异常,于是你就——一在当前运行环境下——一无需再为这个问 题操心了。自然会有人来处理的。我们这就把他介绍给你 异常的参数 第2页共3页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Chapter 9: Error Handling with Exceptions www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✞ 2 ✟ ✠ 3 ✟ ÂkèZ78 Java .^PA/0@A#µ¬ Java ! 1³÷»…Ò2;3#Ɓ4ŽèZ78#$žS+„ä[5! 6%7~89¶ýPQ78èZST#¶ýe:±•èZ# S;@n„34"Ž  èZ©ª(exceptional condition)^?'^>'?@(´34 èZ©ªA<34B'(`#R¯ ä;CA<34"#±F*(DE-FGGH`7 8R\HI÷kèZ©ª#Âk±FGS78R\34G H#Ɓ'F*(DE(in the current context)?@( ´±5'J„F*(DE#i¬ 34 gK(DE R L„èZ,0ü¢  Mn ^\6N¶·LM~MSO¿#³´P,^+ /MQOR ø†‡ST tU±LM±žS V34gW#Ú e¶ý78O»'X «+¶·R^\YZ!s#Ɓ± LM¶ý78¿#K L„^\èZ#µ[‰\]? @´… F±L„èZ"#-^ª¢~ˆ)0ü_;ôÎbU9 Java ÷ `KO#Îb^\èZ÷`Êa# newxyF*\ ](R©\'þ?@´…)#þDèZ÷` referen ce bF*( DEF!c„´1èZ782(d|ò%&…#9~´e^\f E@`?@R\%&R\@ èZ78%& (exception handler)#Ug' D%&b34!hi=`#k% &tjk,´l^©(\]#tj?@(´ m^\LèZno6N# t R\ referen ce9ž'³À-Ì=p dÛ#Ɓ±§¨^þ9´º@n±žSÎb^\øù GH÷`#i R\÷`L„F*(DE#RO ' „ GHIqórK(DE!…R/"L„^\èZ (throwing an exception) ôRÊ if(t == null) throw new NullPointerException(); RO L„…èZ#k± ššF*(DEššþR\3 4윅•x~-`78£:R ›89J± 

Thinking in Java 3 Edition 就像Java中的其它对象,你也可以用new在堆中创建异常,而new 会调用它的构造函数并为它分配内存。所有的标准异常都有两个构造函 数;第一个是默认的构造函数,第二个是要拿一个字符串当参数的,因此 你可以在异常中放入一些相关的信息: throw new NullPointerException("t=null") 就像你将看到的,将来这个字符串可以用各种方法提取出来。 关键词 throw会引发许多很神奇的事情。通常情况下,你会先用new 来创建一个表示错误条件的对象。然后再把这个对象的 reference交给 throw。虽然这个对象不是方法设计要返回的那种对象,但实际上,方 法还是返回这个对象。有一种理解异常处理的简化思路,就是把它想成一 种不同的返回机制。但是这种想法别走得太远,否则就有麻烦了。你也可 以用“抛异常”的方法从方法的作用域里退出。总之,它会返回了一个 值,并且退出了方法或作用域 异常处理与“从方法中正常返回”的相同点就到此为止了,因为它所返回 的地点同正常的方法调用所返回的地点是完全不同的。(它最终是要在某 个异常处理程序里面得到解决的,而这个程序可能离异常发生的地方很 远——与“调用栈( call stack)”隔着很多层。) 此外,你还可以抛出任何 Throwable对象(这是异常的根类)。通常情 况下,你得根据不同的错误抛出不同的异常。错误信息由保存在异常对象 中信息,以及异常类的名字表示。于是上层的运行环境就可以用这个异常 来决定该怎么干了。(通常,异常类型的名字是唯一的信息,异常对象不 会保存什么有用的东西。) 捕捉异常 如果方法抛出了异常,那么必须要有能“捕捉”这个异常,并且处理这个 异常的程序。异常处理有一个好处,就是它能让你集中精力在一个地方解 决问题,然后将处理错误的代码分开来放在另一个地方。 要想理解异常是怎样被捕捉到的,你必须首先懂得“守护区域( guarded reglon)”的概念。这是一段可能会产生异常的代码,并且后面还跟着要 处理这些异常的代码。 Try区块 如果你从方法里面抛出了一个异常(或是在这个方法调用的另一个方法里 面抛出一个异常),那么抛出异常的同时,这个方法会退出运行。如果你 不想被 throw出方法,那么你可以在这个方法的内部建一个特殊的区块 第3页共3页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Thinking in Java 3 rd Edition ✞ 3 ✟ ✠ 3 ✟ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ô Java !U9÷`#±$žS new a!ÎbèZ#µ new ~º9stuQi9'vwx,-vyèZ.-z\stu Q {^\|stuQ#{}\;~^\€F‚Q#Ɓ ±žSèZ!ƒ™^2„GHÊ throw new NullPointerException("t = null"); ô±D#D`R\€žS…?@n†‡„` „ˆõ th row ~C0U[䉥¢  \èZ78%&ÙÚ#µR\%&ž'èZ0ü@ä Žššº(cal l stack)™‰ä[K) š#±³žSL„›ý Th rowable ÷`(RèZ )b^\qrB«

hapter 9: Error Handl 来捕获这个异常。这就被称为“try区块(tyb/ock)”,因为你在这里 “try”各种方法调用。try区块是跟在try关键词后面的程序块。 // Code that might generate exceptions 如果你想在不支持异常处理的编程语言里仔细地检査错误,那么每次调用 方法的时候,你都得在调用代码的外围放上测试错误条件的代码,即便是 在重复调用同一个方法的时候也得这么做。使用异常处理的时候,你把所 有的东西放进try区块,然后在一个地方捕获所有的异常。这就是说,完 成任务的代码和处理错误的代码不会再搅在一起了,因此代码变得更易读 易写了。 异常处理程序 当然,抛出来的异常必须要在什么地方得到处理。这个“地方”就是“异 常处理程序( exception handler)”。此外,你想捉一个异常就要准备 段异常处理程序。异常处理程序会直接跟在try区块后面,用 catch关 键词表示 / Code that might generate 1 catch(Typel idl) t // Handle exceptions of Typel 1 catch(Type2 id2) i // Handle exceptions of Type 2 1 catch(Type3 id3) t Handle exceptions of Type 3 / etc 每条 catch子句(异常处理程序)都像一个微型的,并且有一个且仅有一个 特定类型的参数的方法。异常处理程序可以像使用方法的参数那样使用这 些标识符(id1,id2等等)。有时,由于异常的类型已经给出了足够的信 息,因此你根本就用不到这些标识符,但是它还必须搁在那里。 异常处理程序必须直接跟在try区块后面。如果程序抛出了异常,异常处 理机制就会进来寻找其参数与异常类型相匹配的那些异常处理程序中的第 个。然后进入那条 catch子句,于是它就认为异常已经得到处理了 旦 catch子句结束,寻找异常处理程序的任务就会停下。相匹配的 catch 子句会得到执行;这点不像 switch语句,它得在每个case后面加一 个 break,否则后面指令也会被执行 第4页共4页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Chapter 9: Error Handling with Exceptions www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✞ 4 ✟ ✠ 4 ✟ `R\èZR /"try B«(try block)#ƱR try…?@nºtry B«ª try „ˆõy%&« try { // Code that might generate exceptions } ¶·±²¬­èZ78 %XY® §¨#K‡¸¹º @n"#±.º š¯ƒgP,©ª #4° iº^\@n"$R‡mŽèZ78"#± , -Ÿ ƒ± try B«#xy^\@,-èZR a#½ ͛² ³78 ~þ´^µ…#Ɓ ¶ó·Á ·+…  Fx#L„`èZ;†‡@78R\@ è Z78%&(exception handler)š#±²^\èZ ;y¸^ ¨èZ78%&èZ78%&~Ç|ª try B«y# catch „ ˆõøùÊ try { // Code that might generate exceptions } catch(Type1 id1) { // Handle exceptions of Type1 } catch(Type2 id2) { // Handle exceptions of Type2 } catch(Type3 id3) { // Handle exceptions of Type3 } // etc... ¸© catch N¹ (èZ78%&).ô^\ºÐ#i¬-^\¬»-^\ qeÐ‚Q@nèZ78%&žSôŽ@n‚QKOŽR 2v¼€(id1 id2 ½½)-#ÂkèZÐËÌJ„…FGG H#Ɓ± R2v¼€#+9³¾K èZ78%&Ç|ª try B«y¶·%&L„…èZ#èZ7 82 ~±`¿eU‚QèZÐÀvK2èZ78%&!{ ^\xy±™K© catch N¹#k9 èZËÌ78…^ Á catch N¹ÂÃ#¿eèZ78%&›² ~Àv catch N¹~ R¯ô switch X¹#9¸\ case yÄ^ \ break#ïyÅ$~/

Thinking in Java 3 Edition 注意,在try区块中,有可能会碰到“调用多个不同的方法会产生同一种 异常的”情况,但是这时你只需要一个异常处理程序 中止”还是“继续” 理论上将异常处理划分成两种基本模型。中止模型( temination,也就是 Java和C++所采纳的那种)假定错误是如此的严重,以致于你没办法再 回到错误发生的地方。也就是说,这段程序经过判断认为,它已经没有办 法再挽回这个局势了,于是只能抛出异常,并且希望这个错误别再回来。 还有一种被称为“继续( resumption)”。它的意思是,异常处理程序应 该能作些什么以修补当前的运行环境,然后重新尝试上次出错的那个方 法,它假设第二次能获得成功。“继续”的意思是,处理完异常之后,你 仍然希望能继续运行当前的指令。在这种情况下,异常更像是在调用方 法——如果你想在]ava中得到类似的效果,可以用这个办法来设置运行 环境。(也就是别抛出异常了;调用一个方法来解决这个问题。)此外,还 可以把try区块放到 while循环里面,这样就会重复的运行try区块, 直到你得到满意的结果。 长久以来,程序员所使用的操作系统都是用“继续模式”来处理异常的, 但是最终他们写代码的时候,都会跳开“继续模式”而采用“中止模 式”。所以尽管初听上去,“继续模式”很具吸引力,但是实际上并不是 那么实用。最主要的原因恐怕还是它所导致的耦合( coupling):通常异常 处理程序必须知道异常是从哪里抛出的,并且还要包括专门针对异常抛出 位置的非泛型代码。这使得代码非常难写,也无法维护。碰上会随时产生 异常的大型问题的时候,更是如此。 创建你自己的异常 Java没有限定你只能使用它提供的异常。JDK的异常体系不可能预见到 所有你要报告的异常,所以你可以用你自己创建的异常来表示你的类库可 能会遇到的问题。 要想创建你自己的异常,你必须继承已有的异常,最好是意思上同你要创 建的那个新的异常比较相近的那个(虽然不是经常能做到这一点)。创建 个新的异常类的最简单的做法是直接让编译器为你生成一个默认的构造函 数,这样做几乎不需要写任何代码 //: c09: SimpleExceptionDemo java / Inheriting your own exceptions mport com. bruceeckel. simpletest k class simpleException extends Exception ( public class simpleExceptionDemo private static Test monitor new Test ()i 第5页共5页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Thinking in Java 3 rd Edition ✞ 5 ✟ ✠ 5 ✟ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com Æâ# try B«!#-ž'~Ǻ[\@n~©ü^? èZ «#+R±5;^\èZ78%&     8*gDèZ78È'Íz?ÉÐ!=ÉÐ(temination#$  Java ³ C+ + ,Ê K?)Ëe¶Ì#SÍk±ÀÎnþ p0ü@$ a#R¨%&Ì=‚ƒ#9ËÌÀ-Î nþÏpR\Ðх#k5'L„èZ#i¬z{R\¡þp` ³-^?/"?@(resumption)9âö#èZ78%& '»2†‡SÒÓF*(DE#xyÔk,g¹„K\@ n#9Ëu{}¹'Íg?@âö#78½èZ)y#± Õxz{'?@(F*ÅR? «#èZóôº@ nšš¶·±² Java !Ö×·#žSR\În`uØ( DE($ ¡L„èZ… º^\@n`ÙÚR\34)š#³ žS try B«ƒ wh ile ÙD#RO ~i( try B«# DZÚâ· åÛS`#%&’,Žì»ÄÅ.?@ÉA`78èZ# +•›:+ "#.~J(?@ÉAµÊ!=É A,SñòpÜg´#?@ÉAäÝÞC¢#+­ãgi K‡­ð;áÆßà³9,áÍâf(coupling) <ZèZ 78%&LMèZbãL„#i¬³;äåæçè÷èZL„ éØêÐ RŽ ZI+#$nÔÕÇg~ˆ©ü èZÏÐ34"#ó¶  Java À-ëe±5'Ž9†;èZJD K èZìÄž'Yl ,-±;/0èZ#,S±žS±•ÎbèZ`øù±‘ž '~C34 ;²Îb±•èZ#±?ÉË-èZ#âög±;Î bK\ÔèZíîK\(ŠxÌZ'mR^¯)Îb^ \ÔèZnomnÇ|B !1±üÍ^\|stu Q#ROm^ï;+›ý Ê //: c09:SimpleExceptionDemo.java // Inheriting your own exceptions. import com.bruceeckel.simpletest.*; class SimpleException extends Exception {} public class SimpleExceptionDemo { private static Test monitor = new Test();

hapter 9: Error Handling with Except public void f() throws SimpleException t System. out. println("Throw SimpleException fre throw new SimpleException()i public static void main(String[] args)t SimpleR SimpleExceptionDemo ()i try t sed. f(i 1 catch(SimpleException e)i System. err println("Caught it!") monitor. expect(new string[] i Throw SimpleException from f()", "Caught it! }); 编译器创建了一个默认的构造函数,它会自动地(并且用一种你看不到的 方式)调用基类的默认构造函数。当然,在这个例子中 Simple Exception( String)的构造函数就没有了,但实际上它用的也 不多。正如你将看到的,对异常来说,最重要的是这个类的名字,所以绝 大多数时候这个异常也就够用了。 这里,会用 Systen.err把结果打印到控制台的标准错误流( standarc eror)。对于错误信息来说,送到这里通常会比送到 System.out要 好,因为后者可能会被重定向。如果你将输出送到 System.err,那么 即使是在 System. out被重定向的时候,它还是会被打印在屏幕上的, 这样就能更好地引起用户的注意。 你也可以在你创建的的异常类里定义以 String作参数的构造函数。 //: C09: FullConstructors java import com. bruceeckel simpletest* class My Exception extends Exception t public My Exception()(I public My Exception(String msg)( super(msg)i 1 public class Fullconstructors t private static Test monitor new Test()i public static void f() throws MyException i System. out. println("Throwing MyException from throw new My Exception ()i public static void g( throws MyException System. out. println("Throwing MyException from throw new My Exception("Originated in g(")i 第6页共6页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Chapter 9: Error Handling with Exceptions www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✞ 6 ✟ ✠ 6 ✟ public void f() throws SimpleException { System.out.println("Throw SimpleException from f()"); throw new SimpleException(); } public static void main(String[] args) { SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.f(); } catch(SimpleException e) { System.err.println("Caught it!"); } monitor.expect(new String[] { "Throw SimpleException from f()", "Caught it!" }); } } ///:~ !1Îb…^\|stuQ#9~•ð(i¬^?± @A)º|stuQFx#R\6N! Sim pleException( String)stuQ À-…#+­ãg9$ [P¶±D#÷èZ`a#;R\#,S¤ Ï[Q"R\èZ$ G… R#~ System . err ·ñòó2ôvyõ(standard error)÷kGH`a#öR<Z~ö System . ou t ; #Æyjž'~/e÷¶·±Dø„ö System . err#K‡ 4Ž System . ou t /e÷"#9³~/ñòßùg# RO 'óCµúÆâ ±$žS±ÎbèZe:S String »‚QstuQ //: c09:FullConstructors.java import com.bruceeckel.simpletest.*; class MyException extends Exception { public MyException() {} public MyException(String msg) { super(msg); } } public class FullConstructors { private static Test monitor = new Test(); public static void f() throws MyException { System.out.println("Throwing MyException from f()"); throw new MyException(); } public static void g() throws MyException { System.out.println("Throwing MyException from g()"); throw new MyException("Originated in g()");

Thinking in Java 3 Edition public static void main(String[] args)t F t catch(MyException e) e print stackTrace() ¥y g() 1 catch(MyExcept monitor. expect(new String[] i Throwing MyException from f()", "MYException", 号号\ tat Fu1 Constructors.f\\(.*\\) 号号\ tat Fu11 Constructors.main(.*\)", "Throwing MyException from g()", My Exception: Originated in g()", 号号\ tat Fu11 Constructors,g\\(.*1)", 号号\ tat Fu11 Constructors.main\(.*\\) }); }///: 新增的代码很少: MyException有两个构造函数。第二个通过 super 关键词,明确地用一个 String参数调用了基类的构造函数 处理程序调用了 Throwable类( Exception是从它那里继承的)的 printstackTrace()方法。这个方法会返回“被调用的方法是经过怎 样一个顺序到达异常发生地点”的信息。缺省情况下,这些信息会送到标 准错误流,但是这个方法的重载版也允许你将结果送到其它流 创建自定义的异常还能更进一步。你还可以添进额外的构造函数和成员: //: c09: ExtraFeatures java // Further embellishment of exception clas import com. bruceeckel. simpletest *i private int x public My ption()i] public MyException2(String msg) public My Exception2 (String msg, int x)i public string getMessage()t return "Detail Message: +x+ 第7页共7页 www.wgqqh.com/shhgs/tij.html

Thinking in Java 3 rd Edition ✞ 7 ✟ ✠ 7 ✟ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com } public static void main(String[] args) { try { f(); } catch(MyException e) { e.printStackTrace(); } try { g(); } catch(MyException e) { e.printStackTrace(); } monitor.expect(new String[] { "Throwing MyException from f()", "MyException", "%% \tat FullConstructors.f\\(.*\\)", "%% \tat FullConstructors.main\\(.*\\)", "Throwing MyException from g()", "MyException: Originated in g()", "%% \tat FullConstructors.g\\(.*\\)", "%% \tat FullConstructors.main\\(.*\\)" }); } } ///:~ Ôû ä$ÊM yException -z\stuQ{}\<= su per „ˆõ#üQ^\ String ‚Qº…stuQ 78%&º… Th rowable (Exception b9K?É) printStackTrace( )@nR\@n~op/º@nÌ=N O^\[&ýèZ0ü¯GHþ# «#R2GH~öv yõ#+R\@n$U±D·öU9õ Îb•e:èZ³'ó±^±³žS±šstuQ³Í’Ê //: c09:ExtraFeatures.java // Further embellishment of exception classes. import com.bruceeckel.simpletest.*; class MyException2 extends Exception { private int x; public MyException2() {} public MyException2(String msg) { super(msg); } public MyException2(String msg, int x) { super(msg); this.x = x; } public int val() { return x; } public String getMessage() { return "Detail Message: "+ x + " "+ super.getMessage(); } }

hapter 9: Error Handling with Except public class ExtraFeatures rivate static test monitor new Test ( public static void f() throws My Exception2 t System. out. println("Throwing MyException2 from f()") throw new MyException2() public static void g( throws MyException2 System. out. println("Throwing MyException2 from g()") throw new MyException2(originate public static void h( throws MyException2 k System.out. println("Throwing MyException2 from h()",47 public static void main(String[] args)t f() t catch(MyException2 e)( gO ch (MyException2 e) e print stackTrace( try i h() e print stackTrace() ystemerr println("e. val()=#+e. val() monitor. expect (new String[] t Throwing My Exception2 from f() "MyException2: Detail Message: 0 null 号号 tat ExtraFeatures.f\\(.*\)”, 号号\ tat ExtraFeatures.main\\(.*\\)”, Throwing MyException2 from g(), MyException2: Detail Message: 0 Originated in g()", 号号\ tat ExtraFeatures,g\\(.*\) 号号\ tat ExtraFeatures.main\\(.*\\)", Throwing MyException2 from h() MyException2: Detail Message: 47 Originated 号号\ tat Extrafeatures.h\\(.*1) 号号\ tat Extrafeatures.main\(.*\\)", }); ///:~ 这个异常加了一个数据成员i,一个能读取这个数据的方法和能设定这个 数据的构造函数。此外为了能产生一些更有意思的详细信息,它还覆写了 第8页共8页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Chapter 9: Error Handling with Exceptions www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✞ 8 ✟ ✠ 8 ✟ public class ExtraFeatures { private static Test monitor = new Test(); public static void f() throws MyException2 { System.out.println("Throwing MyException2 from f()"); throw new MyException2(); } public static void g() throws MyException2 { System.out.println("Throwing MyException2 from g()"); throw new MyException2("Originated in g()"); } public static void h() throws MyException2 { System.out.println("Throwing MyException2 from h()"); throw new MyException2("Originated in h()", 47); } public static void main(String[] args) { try { f(); } catch(MyException2 e) { e.printStackTrace(); } try { g(); } catch(MyException2 e) { e.printStackTrace(); } try { h(); } catch(MyException2 e) { e.printStackTrace(); System.err.println("e.val() = " + e.val()); } monitor.expect(new String[] { "Throwing MyException2 from f()", "MyException2: Detail Message: 0 null", "%% \tat ExtraFeatures.f\\(.*\\)", "%% \tat ExtraFeatures.main\\(.*\\)", "Throwing MyException2 from g()", "MyException2: Detail Message: 0 Originated in g()", "%% \tat ExtraFeatures.g\\(.*\\)", "%% \tat ExtraFeatures.main\\(.*\\)", "Throwing MyException2 from h()", "MyException2: Detail Message: 47 Originated in h()", "%% \tat ExtraFeatures.h\\(.*\\)", "%% \tat ExtraFeatures.main\\(.*\\)", "e.val() = 47" }); } } ///:~ R\èZą^\QV͒ i#^\'Á‡R\QV@n³'ueR\ QVstuQš…'©ü^2ó-âö GH#9³+…

Thinking in Java 3 Edition Throwable. getMessage()方法。对于异常类来说, getMessage()有点像 tostring()。 由于异常同其它对象没什么两样,所以你可以不断地用这种方法来增强这 种自定义的异常类。但是要记住,当你把这些 package交给客户程序员 的时候,他们很可能会把这些“浇头”全给扔掉,因为他们可能只是单纯 地找到这个抛出的异常,其它什么都不管。(绝大多数的Java类库中的异 常都是这么用的。) 异常说明 java鼓励你告诉那些调用你方法的客户程序员们,你定义的方法可能会 抛出哪种异常。这是一种很友好的做法,因为这么一来,调用方法的人就 能知道应该写什么样的代码来捕捉潜在的异常了。当然,如果可以得到源 代码的话,客户程序员可以通过査找 throw语句来发现这点,但通常情 况下,他们是得不到类库的源代码的。为了应付这种情况,Java在语法 上提供了支持(同时也是强制你必须使用这种语法),能让你很礼貌地告诉 客户程序员们,这个方法能抛出什么异常,这样客户程序员就能自行处理 了。这就是“异常说明( exception specification)”,它属于方法声明 的一部分,要列在在参数表的后面 异常说明要用 throws关键词,后面再跟上所有可能抛出的异常类型的 清单。所以方法的定义可能会是这样: void f( throws TooBig, TooSmall, Divzero / 如果是 void f(// 这就意味着这个方法不会抛出任何异常(除非是继承自 Runtime Exception的异常,这类异常不需要异常说明就可以从任何 地方抛出——这一点我们以后会讲)。 你不能对异常说明撒谎。如果你的方法产生一个异常但又不作处理,那么 编译器就会提醒你,要么处理这个异常,要么在异常说明部分指明这个方 法会抛出这个异常。通过强化这种从顶层到底层的异常说明,Java提供 了一定程度的在编译时纠正异常的保障 不过还是有个能撒谎的地方:你可以声称方法会抛出一个实际上并不会抛 出的异常。编译器会当真的,它会要求客户程序员像真的会抛出异常那样 第9页共9页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Thinking in Java 3 rd Edition ✞ 9 ✟ ✠ 9 ✟ www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com Th rowable. getM essage( )@n÷kèZ`a# getM essage( )-¯ô toString( ) ÂkèZU9÷`À†‡zO#,S±žSƒR?@n`ûÒR ?•e:èZ+;€#F± R2 packag e J ú%&’ "#›:äž'~ R2 J #ƛ:ž'5o eR\L„èZ#U9†‡.ò(¤Ï[Q Java ‘!è Z.R‡)  Java ±0K2º±@n ú%&’:#±e:@nž'~ L„ã?èZR^?ämn#ÆR‡^`#º@n 'LM+†‡O `èZ…Fx#¶·žSî ¿# ú%&’žS'#;‚Qøy èZaü; th rows „ˆõ#yþªg,-ž'L„èZÐ o,S@ne:ž'~ROÊ void f() throws TooBig, TooSmall, DivZero { //... ¶· void f() { // ... R âû‰R\@n~L„›ýèZ (M?ɕ Ru ntim eException èZ#RèZ;èZaü žSb›ý @L„ššR^¯£:Sy~%) ±'÷èZaü¶·±@n©ü^\èZ+R»78#K‡ !1 ~†±#;‡78R\èZ#;‡èZaü>'ÅüR\@ n~L„R\èZ<=ÒÛR?bKKèZaü#Java †; …^e% ! PèZœ× =³-\'@ʱžS"@n~L„^\­ãgi~L „èZ !1~F!#9~;3 ú%&’ô!~L„èZKO

hapter 9: Error Handl 使用这个方法。这么作的好处就是,它能为异常先占个位子,以后你就能 真的抛出异常而不用去改动已有的代码了。而且对于其实现会真的抛出异 常的 abstract基类和 interface来说,这是相当重要的。 会在编译时进行检査并且强制得到处理的异常被称为 checked exception 捕捉任意类型的异常 要想创建一个“能处理任意类型的异常的”异常处理程序是完全可能的。 要做到这点,你就必须去捕捉异常的基类 Exception了(还有一些其它 类型的基类,但实际上只有 Exception是同编程活动相关的基类): catch(Exception e)t System.err println("Caught an exception")i 这样就能捕获所有的异常了,所以如果你想这么写的话,就应该把它放到 最后,这样它就不会抢在其它处理程序前头把异常给劫走了。 由于 Exception只是那些跟程序员有关的异常类的基类,因此你不能从 它那里得到更多的关于异常的具体信息,不过你也可以调用 Exception 的基类 Throwable的方法 String getMessage o) String getLocalizedMessage) 获取详细信息,或者是用当地语言表示的信息。 String tostring) 返回包括详细说明在内的,这个 Throwable的简短说明。如果有的 话 void printstackTrace void printstackTrace ( Printstream) void printstackTrace java.io PrintWriter) 打印 Throwable以及 Throwable的调用栈轨迹( call stack trace)。调用栈显示了“将你带到异常发生地的”方法调用的顺序。第 个版本会打印到标准错误上,第二和第三个则会打印到你选择的流里 (到第12章,你就会知道为什么要有这两种流)。 Throwable fillInStackTraceo 在 Throwable对象里面记录“栈帧( stack frame)”的当前状态。等 应用程序要重抛错误或异常的时候就要用这些信息了(过一会再作详细讲 解) 第10页共10页 www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com

Chapter 9: Error Handling with Exceptions www.wgqqh.com/shhgs/tij.html email:shhgs@sohu.com ✞ 10 ✟ ✠ 10 ✟ ŽR\@nR‡»7 #9'èZ"\éN#Sy± ' !L„èZµ´#ðË- …µ¬÷kU­1~!L„è Z abstract ³ interface `a#RF; ~ !±§¨i¬Ò278èZ/" checked exception  ;²Îb^\'78›âÐèZèZ78%&½ž' ;mR¯#± ´èZ Exception … (³-^2U9 Ð#+­ãg5- Exception  %$ð„)Ê catch(Exception e) { System.err.println("Caught an exception"); } RO ',-èZ…#,S¶·±²R‡+¿#  9ƒ y#RO9 ~%U978%&* èZJ&Œ… Âk Exception 5K2ª%&’-„èZ#Ɓ±'b 9Kó[„kèZÝìGH#=±$žSº Exception  Th rowable @nÊ String getM essage( ) String getLocalizedM essage( ) ‡ GH#tjFXYøùGH String toString( ) opäå aüw#R\ Th rowable n'aü¶·- ¿ void printStackTrace( ) void printStackTrace( PrintStream ) void printStackTrace(java. io. PrintWriter) ñò Th rowable ST Th rowable º()(cal l stack trace)ºù…D±*èZ0ü@nº[&{ ^\~ñòvyg#{}³{+\ï~ñò±,-õ ({ 1 2 7#± ~LM†‡;-Rz?õ) Th rowable fil l InStackTrace( )  Th rowable ÷`€./(stack fram e)F*0½ %&;LtèZ" ;R2GH…(=^~þ» % Ù)

点击下载完整版文档(PDF)VIP每日下载上限内不扣除下载券和下载次数;
按次数下载不扣除下载券;
24小时内重复下载只扣除一次;
顺序:VIP每日次数-->可用次数-->下载券;
共41页,可试读14页,点击继续阅读 ↓↓
相关文档

关于我们|帮助中心|下载说明|相关软件|意见反馈|联系我们

Copyright © 2008-现在 cucdc.com 高等教育资讯网 版权所有