在JAVA中收到程序报错,将堆栈信息打印出来是一个好习惯,但是在catch到exception之后,发现有两个方法都和堆栈信息有关,一个是getStackTrace,一个是printStackTrace,那么他们的区别是什么?
我们从源码的角度来分析:
(1)getStackTrace()
public StackTraceElement[] getStackTrace() {
return getOurStackTrace().clone();
}
private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
return stackTrace;
}
(2)printStackTrace()
public void printStackTrace() {
printStackTrace(System.err);
}
/**
* Prints this throwable and its backtrace to the specified print stream.
*
* @param s {@code PrintStream} to use for output
*/
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
Set<Throwable> dejaVu =
Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this);
synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement);
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}
getStackTrace()返回的是通过getOurStackTrace方法获取的StackTraceElement[]数组,而这个StackTraceElement是ERROR的每一个cause by的信息。
printStackTrace()返回的是一个void值,但是可以看到其方法内部将当前传入打印流锁住,然后同样通过getOurStackTrace方法获取的StackTraceElement[]数组,只不过printStackTrace()方法直接打印出来了。而getStackTrace()则是得到数组,使用者可以根据自己的需求去得到打印信息,相比printStackTrace()会更细一些。
这里指的一提的是slf4j的log方法,如果放入Exception对象,则会自动打印出其堆栈信息,不必要再专门去转流写入日志。