printStackTrace()直接输出异常调用栈到System.err,适合本地调试;getStackTrace()返回StackTraceElement[]供程序化分析;需用getCause()穿透嵌套异常获取根因,且注意getMessage()可能为null。

用 printStackTrace() 快速定位异常源头
开发时最常用的调试方式,直接把异常的完整调用栈输出到标准错误流。它不返回字符串,而是立即打印,适合本地调试或日志不完善的场景。
注意:printStackTrace() 默认输出到 System.err,在某些容器或日志框架中可能被截断或丢失;生产环境不建议直接使用,应配合日志系统。
- 想重定向输出位置?传入
PrintStream或PrintWriter参数,例如e.printStackTrace(new PrintWriter(stringWriter)) - 只关心异常类型和消息?用
e.toString(),但会丢掉堆栈 - 需要结构化提取类名、行号?必须解析堆栈元素,不能靠字符串匹配
用 getStackTrace() 获取可遍历的堆栈帧
getStackTrace() 返回 StackTraceElement[],每个元素包含类名、方法名、文件名和行号,是程序化分析异常路径的基础。
这个数组按“从抛出点到最外层调用”顺序排列,索引 0 就是异常最初发生的位置。
立即学习“Java免费学习笔记(深入)”;
- 获取第一帧(真正出错的地方):
e.getStackTrace()[0].getClassName()+.getLineNumber() - 过滤掉 JDK 内部调用?遍历数组,跳过
java.、javax.、sun.开头的类名 - 注意:JVM 可能因优化(如内联)省略部分帧,
getStackTrace()返回长度可能为 0(极少见,但可能)
用 Throwable.getLocalizedMessage() 和 getMessage() 区分用户提示与开发者信息
getMessage() 返回构造异常时传入的原始字符串,通常含技术细节(如 SQL 错误码、空指针字段名);getLocalizedMessage() 本意是返回本地化消息,但多数 JDK 实现直接委托给 getMessage(),除非子类重写。
实际项目中,不要依赖 getLocalizedMessage() 做国际化,它不可靠。真正做多语言提示,应根据异常类型查资源包。
-
NullPointerException的getMessage()可能为null—— 需判空,否则后续调用报 NPE -
SQLException的getMessage()通常很长,含 SQL 状态码和驱动信息,适合记录,不适合前端展示 - 自定义异常务必在构造器里明确设置有意义的
message,别留空或写“error occurred”
捕获嵌套异常时必须用 getCause() 向下穿透
Java 异常链(如 new RuntimeException("wrap", cause))中,根因往往藏在 cause 里。只看最外层异常的 message 和 stack trace,大概率错过真实问题。
尤其在 Spring、MyBatis 等框架中,业务异常常被包装成 RuntimeException,原始 SQLException 或 IOException 就在 getCause() 里。
- 安全获取根本原因:循环调用
getCause()直到返回null,但要防循环引用(JDK 7+ 已处理) - Spring 提供了
org.springframework.util.ExceptionUtils.getRootCause(),可直接用 - 日志记录时,建议同时输出
e.getMessage()和e.getCause() != null ? e.getCause().getMessage() : "no cause"
getCause() 一定非空,或者认为 getStackTrace() 总能拿到源码行号。










