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èZe: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õ Îbe:è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±SR?@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<=¨e th row X¹`01R¯#+<Z «#:î R?«#Java Xn g; ¬($Ò2±R?Xn)#'B±ä0 ú%&:#R\@n'LèZ#RO ú%& '78 R èZaü (exception specification)#9jk@nü ^>'#;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ý @LR^¯£:Sy~%) ±'÷èZaü¶·±@n©ü^\èZ+R»78#K !1 ~±#;78R\èZ#;èZaü>'ÅüR\@ n~LR\è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µ´#ðË- µ¬÷kU1~!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#tjFXYøù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 (=^~þ» % Ù)