按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
制来说,其中一个可能有用的是getClass(),它的作用是返回一个对象,用它代表这个对象的类。我们可依
次用getName()或toString()查询这个Class 类的名字。亦可对 Class 对象进行一些复杂的操作,尽管那些
操作在违例控制中是不必要的。本章稍后还会详细讲述 Class 对象。
下面是一个特殊的例子,它展示了 Exception 方法的使用(若执行该程序遇到困难,请参考第3 章3。1。2 小
节“赋值”):
//: ExceptionMethods。java
// Demonstrating the Exception Methods
package c09;
public class ExceptionMethods {
public static void main(String'' args) {
try {
266
…………………………………………………………Page 268……………………………………………………………
throw new Exception(〃Here's my Exception〃);
} catch(Exception e) {
System。out。println(〃Caught Exception〃);
System。out。println(
〃e。getMessage(): 〃 + e。getMessage());
System。out。println(
〃e。toString(): 〃 + e。toString());
System。out。println(〃e。printStackTrace():〃);
e。printStackTrace();
}
}
} ///:~
该程序输出如下:
Caught Exception
e。getMessage(): Here's my Exception
e。toString(): java。lang。Exception: Here's my Exception
e。printStackTrace():
java。lang。Exception: Here's my Exception
at ExceptionMethods。main
可以看到,该方法连续提供了大量信息——每类信息都是前一类信息的一个子集。
9。2 。5 重新“掷”出违例
在某些情况下,我们想重新掷出刚才产生过的违例,特别是在用Exception 捕获所有可能的违例时。由于我
们已拥有当前违例的句柄,所以只需简单地重新掷出那个句柄即可。下面是一个例子:
catch(Exception e) {
System。out。println(〃一个违例已经产生〃);
throw e;
}
重新“掷”出一个违例导致违例进入更高一级环境的违例控制器中。用于同一个 try 块的任何更进一步的
catch 从句仍然会被忽略。此外,与违例对象有关的所有东西都会得到保留,所以用于捕获特定违例类型的
更高一级的控制器可以从那个对象里提取出所有信息。
若只是简单地重新掷出当前违例,我们打印出来的、与printStackTrace()内的那个违例有关的信息会与违
例的起源地对应,而不是与重新掷出它的地点对应。若想安装新的堆栈跟踪信息,可调用
fillInStackTrace(),它会返回一个特殊的违例对象。这个违例的创建过程如下:将当前堆栈的信息填充到
原来的违例对象里。下面列出它的形式:
//: Rethrowing。java
// Demonstrating fillInStackTrace()
public class Rethrowing {
public static void f() throws Exception {
System。out。println(
〃originating the exception in f()〃);
throw new Exception(〃thrown from f()〃);
}
public static void g() throws Throwable {
try {
f();
} catch(Exception e) {
267
…………………………………………………………Page 269……………………………………………………………
System。out。println(
〃Inside g(); e。printStackTrace()〃);
e。printStackTrace();
throw e; // 17
// throw e。fillInStackTrace(); // 18
}
}
public static void
main(String'' args) throws Throwable {
try {
g();
} catch(Exception e) {
System。out。println(
〃Caught in main; e。printStackTrace()〃);
e。printStackTrace();
}
}
} ///:~
其中最重要的行号在注释内标记出来。注意第 17行没有设为注释行。它的输出结果如下:
originating the exception in f()
Inside g(); e。printStackTrace()
java。lang。Exception: thrown from f()
at Rethrowing。f(Rethrowing。java:8)
at Rethrowing。g(Rethrowing。java:12)
at Rethrowing。main(Rethrowing。java:24)
Caught in main; e。printStackTrace()
java。lang。Exception: thrown from f()
at Rethrowing。f(Rethrowing。java:8)
at Rethrowing。g(Rethrowing。java:12)
at Rethrowing。main(Rethrowing。java:24)
因此,违例堆栈路径无论如何都会记住它的真正起点,无论自己被重复“掷”了好几次。
若将第 17 行标注(变成注释行),而撤消对第 18 行的标注,就会换用fillInStackTrace(),结果如下:
originating the exception in f()
Inside g(); e。printStackTrace()
java。lang。Exception: thrown from f()
at Rethrowing。f(Rethrowing。java:8)
at Rethrowing。g(Rethrowing。java:12)
at Rethrowing。main(Rethrowing。java:24)
Caught in main; e。printStackTrace()
java。lang。Exception: thrown from f()
at Rethrowing。g(Rethrowing。java:18)
at Rethrowing。main(Rethrowing。java:24)
由于使用的是fillInStackTrace() ,第18 行成为违例的新起点。
针对 g()和 main(),Throwable 类必须在违例规格中出现,因为fillInStackTrace()会生成一个 Throwable
对象的句柄。由于 Throwable 是 Exception 的一个基础类,所以有可能获得一个能够“掷”出的对象(具有
Throwable 属性),但却并非一个 Exception (违例)。因此,在main()中用于Exception 的句柄可能丢失
自己的目标。为保证所有东西均井然有序,编译器强制Throwable 使用一个违例规范。举个例子来说,下述
268
…………………………………………………………Page 270……………………………………………………………
程序的违例便不会在main()中被捕获到:
//: ThrowOut。java
public class ThrowOut {
public static void
main(String'' args) throws Throwable {
try {
throw new Throwable();
} catch(Exception e) {
System。out。println(〃Caught in main()〃);
}
}
} ///:~
也有可能从一个已经捕获的违例重新“掷”出一个不同的违例。但假如这样做,会得到与使用
fillInStackTrace()类似的效果:与违例起源地有关的信息会全部丢失,我们留下的是与新的 throw 有关的
信息。如下所示:
//: RethrowNew。java
// Rethrow a different object from the one that
// was caught
public class RethrowNew {
public static void f() throws Exception {
System。out。println(
〃originating the exception in f()〃);
throw new Exception(〃thrown from f()〃);
}
public static void main(String'' args)