e.printStackTrace() 方法大家都熟悉不过了,可以将异常栈从栈顶开始打印至控制台。
我们也可通过 e.getStackTrace() 获取一个包含异常栈每一帧的数组,数组中的第一个元素为栈顶元素。
下面这个例子展示了可以通过数组返回的 StackTraceElement 对象获取行数、类名、方法名等信息。
public class WhoCalled {
public static void f() {
try {
throw new Exception();
} catch (Exception e) {
for (StackTraceElement ste : e.getStackTrace()) {
System.out.print("line:"+ste.getLineNumber());
System.out.print("\t"+"className:"+ste.getClassName());
System.out.print("\t"+"methodName:"+ste.getMethodName());
System.out.println();
}
}
}
public static void g(){
f();
}
public static void h(){
f();
}
public static void main(String[] args) {
f();
System.out.println("-----------------------");
g();
System.out.println("-----------------------");
h();
System.out.println("-----------------------");
}
}
line:12 className:mtn.baymax.charpter12.WhoCalled methodName:f
line:32 className:mtn.baymax.charpter12.WhoCalled methodName:main
-----------------------
line:12 className:mtn.baymax.charpter12.WhoCalled methodName:f
line:24 className:mtn.baymax.charpter12.WhoCalled methodName:g
line:34 className:mtn.baymax.charpter12.WhoCalled methodName:main
-----------------------
line:12 className:mtn.baymax.charpter12.WhoCalled methodName:f
line:28 className:mtn.baymax.charpter12.WhoCalled methodName:h
line:36 className:mtn.baymax.charpter12.WhoCalled methodName:main
-----------------------
当我们在捕获一个异常后,假设需要再重新向上抛出异常,但是想把异常进行阻断,不想让调用者看到之前的调用信息,之后再从当前位置重新抛出,该如何操作呢?
通过 fillInStackTrace() 方法返回的 Throwable 对象(Throwable 是 Exception 的基类),转换成 Exception 再进行抛出,就可实现异常阻断的效果。
下例中的 g() 为正常接力向上抛出异常,而 h() 则用 fillInStackTrace() 将异常阻断后再进行抛出。
从打印结构可以看出,从 h() 抛出的异常栈已看不到 f() 方法的调用信息。
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 Exception {
try {
f();
} catch (Exception e) {
System.out.println("Inside g(),e.printStackTrace()");
e.printStackTrace(System.out);
throw e;
}
}
public static void h() throws Exception {
try {
f();
} catch (Exception e) {
System.out.println("Inside h(),e.printStackTrace()");
e.printStackTrace(System.out);
throw (Exception)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
g();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
try {
h();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
}
}
originating the exception in f()
Inside g(),e.printStackTrace()
java.lang.Exception: thrown from f()
at mtn.baymax.charpter12.Rethrowing.f(Rethrowing.java:12)
at mtn.baymax.charpter12.Rethrowing.g(Rethrowing.java:17)
at mtn.baymax.charpter12.Rethrowing.main(Rethrowing.java:37)
main:printStackTrace()
java.lang.Exception: thrown from f()
at mtn.baymax.charpter12.Rethrowing.f(Rethrowing.java:12)
at mtn.baymax.charpter12.Rethrowing.g(Rethrowing.java:17)
at mtn.baymax.charpter12.Rethrowing.main(Rethrowing.java:37)
originating the exception in f()
Inside h(),e.printStackTrace()
java.lang.Exception: thrown from f()
at mtn.baymax.charpter12.Rethrowing.f(Rethrowing.java:12)
at mtn.baymax.charpter12.Rethrowing.h(Rethrowing.java:27)
at mtn.baymax.charpter12.Rethrowing.main(Rethrowing.java:43)
main:printStackTrace()
java.lang.Exception: thrown from f()
at mtn.baymax.charpter12.Rethrowing.h(Rethrowing.java:31)
at mtn.baymax.charpter12.Rethrowing.main(Rethrowing.java:43)
Process finished with exit code 0
接下来,我们再来看看另一种情况,在一个位置产生异常后,需要生成新的异常,但同时需要带上初始异常的信息,这时又该如何解决呢?
我们在新的异常生成后,使用 initCause() 将两个异常链接起来。
public class ContactException {
public static void f() throws Exception {
throw new Exception();
}
public static void g(){
try {
f();
} catch (Exception e) {
RuntimeException runtimeException = new RuntimeException();
runtimeException.initCause(e);
runtimeException.printStackTrace();
}
}
public static void main(String[] args) {
g();
}
}
java.lang.RuntimeException
at mtn.baymax.charpter12.ContactException.g(ContactException.java:18)
at mtn.baymax.charpter12.ContactException.main(ContactException.java:25)
Caused by: java.lang.Exception
at mtn.baymax.charpter12.ContactException.f(ContactException.java:11)
at mtn.baymax.charpter12.ContactException.g(ContactException.java:16)
... 1 more
本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。
若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!