e.printStackTrace和System.out.println(e)的区别

35

这可能是一个新手问题,但似乎每个人都使用 e.printStackTrace(),但在异常处理时我总是使用 System.out.println(e)。两者有何区别,为什么 e.printStackTrace() 更可取?


尝试一下,你就会看到它们的差异。你也可以阅读printStackTrace()的代码。 - Peter Lawrey
7个回答

50

与@Brian所指出的不同,使用的输出流并不相同,但详细程度也不同 - 您可以尝试下面的简单测试。 输出:

使用 println: 您只知道抛出了什么异常

java.lang.UnsupportedOperationException: 尚未实现

使用 printStackTrace: 您还可以知道是什么引起了异常 (行号+调用堆栈)

java.lang.UnsupportedOperationException: 尚未实现
at javaapplication27.Test1.test(Test1.java:27)
at javaapplication27.Test1.main(Test1.java:19)

public static void main(String[] args){
    try {
        test();
    } catch (UnsupportedOperationException e) {
        System.out.println(e);
        e.printStackTrace();
    }
}

private static void test() {
    throw new UnsupportedOperationException("Not yet implemented");
}

9
如果你使用System.out.println,那么你将把错误信息输出到stdout而不是stderr
传统上,将错误信息输出到标准错误流,这样可以将正常的输出和错误输出分离以便筛选。这是命令行工具的一种常见做法,因此遵循这个惯例是一个好主意。
例如:
myCommand 2> /tmp/errors > /tmp/results

将错误信息写入一个日志文件,将结果写入另一个日志文件。根据您的shell/调用过程等,您可以组合此信息,丢弃错误,如果抛出任何错误,则进行反应等。有关更多信息,请参见此处
使用printStackTrace()是一个好主意,因为它会显示异常发生的位置。这对于跟踪意外错误非常有价值,因为它会直接(详细)指向您遇到错误的确切位置。

在Unix系统中,也许在Windows系统中也可以(我不确定),你可以将标准输出和错误消息分别重定向到不同的文件中,就像这样:yourProgram > ~/fileThatContainsStandardOutput.txt 2> ~/fileThatContainsErrors.txt - Kasper van den Berg
从什么到什么?stdout 和 stderr?我已尝试上面的说明。 - Brian Agnew
在Eclipse中,stdout在控制台中以黑色显示,而stderr以红色显示。更一般地说,它们只是两个输出流,您可以随意处理。 - slim

8
`System.out.println(e)` 相当于 `System.out.println(e.toString())`,其中 `System.out` 是一个 `PrintStream`,`PrintStream.println(Object o)` 调用了 `PrintStream.println(o.toString())`。
`e.toString()` 返回类的名称和异常的 `getLocalizedMessage()`。
`e.printStackTrace()` 将该信息写入到 `System.err`(而不是 `System.out`),并且还包括堆栈跟踪,即导致异常的方法链。这是有用的信息。
我经常想如果有一个方法可以返回由 `e.printStackTrace()` 输出的信息的字符串就好了。但由于没有这样的方法,你必须使用 `e.getStackTrace()` 并编写自己的例程来输出结果数组中的 `StackTraceElements`。

1
有一个 e.getStackTrace() 方法可以返回一个对象数组。此外,printStackTrace 方法接受一个 PrintStreamPrintWriter 参数 - 因此您可以将其传递给 StringWriter 对象或任何其他流以提取数据。 - interDist
OutputStream.println 很令人困惑,因为 OutputStream 没有任何方法。它只在 PrintStream 中定义。 - crackerplace
那么 System.err.println(e); 等同于 e.getStackTrace() 吗? - roottraveller
@roottraveller。System.err.println(e);具有void返回类型,并将异常的toString()打印到stderr中。该输出中没有堆栈跟踪。e.getStackTrace()返回一个StackTraceElement数组。这些都在JavaDoc中,很容易自己尝试。 - slim

3

由于e.printStackTrace();的输出是System.err,而我通常将我的应用程序日志输出到文件中,因此建议您同时使用System.errSystem.out来输出错误信息。

public static void log(Exception e) {
    e.printStackTrace(); // This goes to System.err
    e.printStackTrace(System.out);
}

这样你就可以在日志文件中(如果有的话)和控制台中看到错误信息。


1
谢谢您解释如何使用System.out作为输入参数将堆栈跟踪重定向到控制台。 - Martijn

1

System.out.println(e) 不会给你堆栈跟踪,只会输出错误消息和异常类型,并打印到标准输出而不是错误输出。


0
下面的程序展示了细节上的不同之处: System.out.println(e);:仅显示异常。例如:java.lang.ArithmeticException: / by zero e.printStackTrace();:显示异常的详细信息以及在程序中引起异常的位置和行号,例如:java.lang.ArithmeticException: / by zero at test.Test.main(Test.java:7)
package test;

public class Test {

    public static void main(String args[]) {
        try {
            System.out.println(12 / 0);

        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }

    }
}

0

使用System.out.println(e)只能知道抛出了什么异常,但是使用e.printStackTrace()可以获取关于抛出的异常以及引起它的原因的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接