你应该调用ex.printStackTrace()
。
使用System.out.println(ex)
会隐藏很多有用的信息,甚至可能是至关重要的信息。例如,如果你运行以下代码:
package com.example;
public class Main {
public static void main(String[] args) {
try {
throwException();
} catch (Exception ex) {
System.out.println(ex);
}
}
public static void throwException() throws Exception {
throw new Exception("something went wrong");
}
}
您将获得以下输出:
java.lang.Exception: something went wrong
那只告诉你异常的类型和错误信息。对于简单的应用程序,这可能足够知道问题是什么以及在哪里。但考虑一个有数千行代码的复杂应用程序;这种异常报告不会告诉您问题发生的位置。
现在将 System.out.println(ex)
替换为 ex.printStackTrace()
,然后您将看到新的输出:
java.lang.Exception: something went wrong
at com.example.Main.throwException(Main.java:14)
at com.example.Main.main(Main.java:7)
这是堆栈跟踪。从堆栈跟踪中,您可以看到执行流程,还可以查看哪些特定代码行抛出了异常。请注意,您可以配置编译以丢弃调试信息,这意味着您将停止获得源文件名称和行号,但仍将提供类和方法名称(总比没有好)。
Java中的异常不仅如此。异常还可以具有原因以及多个压制异常。 这在Throwable
文档中有更详细的描述。这里是一个(人为制造的)例子:
package com.example;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
throwException();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void throwException() throws Exception {
IOException ioe = new IOException("could not write to stream");
ioe.addSuppressed(new IOException("unable to close stream"));
throw new Exception("something went wrong", ioe);
}
}
这将产生以下输出:
java.lang.Exception: something went wrong
at com.example.Main.throwException(Main.java:19)
at com.example.Main.main(Main.java:9)
Caused by: java.io.IOException: could not write to stream
at com.example.Main.throwException(Main.java:16)
... 1 more
Suppressed: java.io.IOException: unable to close stream
at com.example.Main.throwException(Main.java:17)
... 1 more
如果使用
System.out.println(ex)
,则无法获取任何
Caused by:
或
Suppressed:
部分。这意味着您不知道实际问题是什么,也不知道是否存在隐藏的问题,这很可能会使修复问题变得更加困难。另外,
System.out.println(ex)
和
ex.printStackTrace()
之间还有另一个区别。前者将打印到
标准输出流(即
System.out
),而后者将打印到
标准错误流(即
System.err
)。由于异常属于错误,因此将其打印到错误流是有意义的,但是您可以通过
Throwable#printStackTrace(PrintStream)
或
Throwable#printStackTrace(PrintWriter)
更改目标。例如,
ex.printStackTrace(System.out)
将在标准输出中打印堆栈跟踪。最后,对于“真正”的应用程序,您可能希望使用日志记录框架。这些框架可以输出更多信息,例如报告异常的线程以及异常发生的时间戳。请查看
What is a stack trace, and how can I use it to debug my application errors?问答,以更好地了解堆栈跟踪及其有用性。
System.out.println(ex);
打印会输出ex.toString()
,这可能不是很有用。要打印出错误信息,请使用ex.printStackTrace();
。 - c0der