关于java:printStackTrace()和toString()之间的区别

Difference between printStackTrace() and toString()

我很好奇printstacktrace()和toString()之间有什么区别。乍一看,他们似乎做了完全相同的事情。

代码:

1
2
3
4
5
6
7
try {
// Some code
} catch (Exception e)
   e.printStackTrace();
   // OR
   e.toString()
}


不,有一个重要的区别!使用ToString,您只有异常类型和错误消息。使用printstacktrace()可以获得异常的整个stacktrace,这对调试非常有帮助。

system.out.println(toString())示例:

1
java.io.FileNotFoundException: yourFile.txt (The system cannot find the file specified)

printstacktrace()示例:

1
2
3
4
5
java.io.FileNotFoundException: yourFile.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:106)
at java.io.FileReader.(FileReader.java:55)
at ReadFromFile.main(ReadFromFile.java:14)

要对整个stacktrace创建字符串,我通常使用以下方法:

1
2
3
4
5
6
7
8
public static String exceptionStacktraceToString(Exception e)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream ps = new PrintStream(baos);
    e.printStackTrace(ps);
    ps.close();
    return baos.toString();
}

还要注意,简单地调用toString()只返回一个字符串,不会打印出任何内容。


要将stacktrace转换为字符串,我使用的较短实现是:

1
2
3
4
public static String exceptionStacktraceToString(Exception e)
{
    return Arrays.toString(e.getStackTrace());
}


不,有很大的不同。如果您只调用toString,它将不会打印任何内容—它只返回一个字符串。一个仅仅是e.toString();的catch块是无用的。(正如Martijn指出的,还有堆栈跟踪的问题。)

但我个人也不会使用——我会使用一个日志库(log4j、java.util.logging等),它将Throwable本身作为参数,并且会有效地格式化它——包括堆栈跟踪,可能会被截断以避免重复。


我想你想得到Throwable.printStackTrace()的输出,就像我想要的一样。我检查了Java源代码,把EDCOX1的9个字放在一起,而不是写一个EDCOX1×10。它比@martijncoteaux解决方案更全面,但对我来说有点像黑客。

至于你的答案,你可以看到,Throwable.toString()只是Throwable.printStackTrace()的一部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static String getStackTraceString(Throwable e) {
    return getStackTraceString(e,"");
}

private static String getStackTraceString(Throwable e, String indent) {
    StringBuilder sb = new StringBuilder();
    sb.append(e.toString());
    sb.append("
"
);

    StackTraceElement[] stack = e.getStackTrace();
    if (stack != null) {
        for (StackTraceElement stackTraceElement : stack) {
            sb.append(indent);
            sb.append("\tat");
            sb.append(stackTraceElement.toString());
            sb.append("
"
);
        }
    }

    Throwable[] suppressedExceptions = e.getSuppressed();
    // Print suppressed exceptions indented one level deeper.
    if (suppressedExceptions != null) {
        for (Throwable throwable : suppressedExceptions) {
            sb.append(indent);
            sb.append("\tSuppressed:");
            sb.append(getStackTraceString(throwable, indent +"\t"));
        }
    }

    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(indent);
        sb.append("Caused by:");
        sb.append(getStackTraceString(cause, indent));
    }

    return sb.toString();
}


当引发异常时,toString ()给出异常类的名称,printStackTrace ()给出在应用程序中引发异常时方法执行的入口层次结构。

为了代码

1
2
3
4
5
6
7
8
    try
    {
        List<String>  n =new ArrayList<String>();
        String i = n.get(3);
    }catch (Exception e) {
        e.printStackTrace();
    }
   }

e.printStackTrace()将给予

1
2
3
4
java.lang.IndexOutOfBoundsException: Index: 3, Size: 0
    at java.util.ArrayList.RangeCheck(ArrayList.java:547)
    at java.util.ArrayList.get(ArrayList.java:322)
    at com.o2.business.util.Trial.test(CommonUtilsTest.java:866)

虽然江户记1〔7〕不会像乔恩在回答中写的那样打印任何东西。


有一个开源的Java库称为MGNtutul(由我编写),它提供了几种方法,允许您将STACKTROPE提取为字符串,也可以选择基于参数封装前缀的过滤器。有关方法public static java.lang.string getstacktrace(java.lang.throwable e,布尔切割,java.lang.string相关包)图书馆位于Maven Central和Github。


这是我使用的作为String的完整堆栈跟踪

1
2
3
4
5
public static @NotNull String toString(@NotNull Throwable e) {
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    return sw.toString();
}