Java Throwable 类
最后修改时间:2025 年 4 月 13 日
java.lang.Throwable 类是 Java 中所有错误和异常的超类。它是 Java 异常处理机制的基础。理解 Throwable 对于正确的错误处理至关重要。
Throwable 包含创建时执行堆栈的快照。它提供了访问此堆栈跟踪和获取错误原因的方法。所有异常和错误都继承自 Throwable,使其成为 Java 错误层次结构的根。
Throwable 类方法
Throwable 类提供了几种用于错误处理和调试的方法。主要方法包括 getMessage、getCause、printStackTrace 和 getStackTrace。这些方法有助于有效地诊断和处理错误。
public class Throwable implements Serializable {
public Throwable() {...}
public Throwable(String message) {...}
public Throwable(String message, Throwable cause) {...}
public Throwable(Throwable cause) {...}
public String getMessage() {...}
public String getLocalizedMessage() {...}
public Throwable getCause() {...}
public void printStackTrace() {...}
public StackTraceElement[] getStackTrace() {...}
public void setStackTrace(StackTraceElement[] stackTrace) {...}
public final void addSuppressed(Throwable exception) {...}
public final Throwable[] getSuppressed() {...}
}
上面的代码显示了 Throwable 类提供的主要方法。这些方法允许检查错误详细信息、原因以及发生错误时的执行堆栈跟踪。
基本异常处理
此示例演示了使用 try-catch 块的基本异常处理。我们捕获除以零时发生的 ArithmeticException。 catch 块打印异常消息和堆栈跟踪。
package com.zetcode;
public class Main {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
public static int divide(int a, int b) {
return a / b;
}
}
执行时,此代码会捕获除以零引发的 ArithmeticException。 catch 块打印错误消息和完整的堆栈跟踪,显示异常发生的位置。 这有助于调试问题。
自定义异常类
此示例显示了如何通过扩展 Exception 来创建自定义异常。我们定义了一个 InsufficientFundsException,其中包括当前余额和请求的金额。这提供了有关错误的更多上下文。
package com.zetcode;
class InsufficientFundsException extends Exception {
private double balance;
private double amount;
public InsufficientFundsException(double balance, double amount) {
super("Insufficient funds: balance=" + balance + ", amount=" + amount);
this.balance = balance;
this.amount = amount;
}
public double getBalance() { return balance; }
public double getAmount() { return amount; }
}
class Account {
private double balance;
public Account(double balance) { this.balance = balance; }
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException(balance, amount);
}
balance -= amount;
}
}
public class Main {
public static void main(String[] args) {
Account account = new Account(100);
try {
account.withdraw(150);
} catch (InsufficientFundsException e) {
System.err.println(e.getMessage());
System.err.println("Short by: " + (e.getAmount() - e.getBalance()));
}
}
}
自定义异常提供了有关错误条件的详细信息。 捕获后,我们可以访问标准消息和附加字段。 这使得错误处理更具信息性和精确性。
链式异常
Java 允许链接异常,以便在包装异常时保留原始原因。此示例演示了如何使用接受原因的 Throwable 构造函数来创建和处理链式异常。
package com.zetcode;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
processFile("nonexistent.txt");
} catch (ApplicationException e) {
System.err.println("Caught: " + e.getMessage());
System.err.println("Original cause: " + e.getCause().getMessage());
e.getCause().printStackTrace();
}
}
public static void processFile(String filename) throws ApplicationException {
try {
// Simulate file operation that fails
throw new IOException("File not found: " + filename);
} catch (IOException e) {
throw new ApplicationException("Failed to process file", e);
}
}
}
class ApplicationException extends Exception {
public ApplicationException(String message, Throwable cause) {
super(message, cause);
}
}
此示例显示了一个常见的模式,其中低级别的 IOException 被包装在高级别的 ApplicationException 中。 保留了原始原因,以后可以访问。 这在提供特定于应用程序的语义的同时,保持了完整的错误上下文。
打印堆栈跟踪
Throwable 类提供了几种打印堆栈跟踪的方法。 此示例演示了访问和打印堆栈跟踪信息的不同方法,包括标准 printStackTrace 和 getStackTrace 方法。
package com.zetcode;
public class Main {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
// Standard stack trace to stderr
e.printStackTrace();
// Print stack trace to System.out
e.printStackTrace(System.out);
// Access stack trace elements programmatically
System.out.println("\nStack trace elements:");
for (StackTraceElement element : e.getStackTrace()) {
System.out.println(element);
}
}
}
public static void method1() {
method2();
}
public static void method2() {
method3();
}
public static void method3() {
throw new RuntimeException("Test exception");
}
}
此代码演示了访问堆栈跟踪信息的三种方法。 标准 printStackTrace 输出到 stderr,而重载版本可以重定向输出。 getStackTrace 方法允许以编程方式访问每个堆栈帧。
抑制异常
Java 7 引入了抑制异常来处理发生多个异常的情况,例如在 try-with-resources 块中。此示例显示了如何使用 getSuppressed 访问抑制的异常。
package com.zetcode;
class Resource implements AutoCloseable {
private String name;
public Resource(String name) { this.name = name; }
public void use() throws Exception {
throw new Exception("Error using resource " + name);
}
@Override
public void close() throws Exception {
throw new Exception("Error closing resource " + name);
}
}
public class Main {
public static void main(String[] args) {
try (Resource res1 = new Resource("1");
Resource res2 = new Resource("2")) {
res1.use();
res2.use();
} catch (Exception e) {
System.out.println("Caught: " + e.getMessage());
System.out.println("Suppressed exceptions:");
for (Throwable t : e.getSuppressed()) {
System.out.println(" - " + t.getMessage());
}
}
}
}
在此 try-with-resources 示例中,use() 和 close() 方法都会抛出异常。 主要异常是来自 use() 的异常,而 close() 异常被添加为抑制的异常。 这会将所有错误信息保存在单个异常对象中。
错误 vs 异常
此示例演示了 Errors 和 Exceptions 之间的区别,它们都扩展了 Throwable。 Errors 通常表示应用程序不应尝试捕获的严重问题,而 Exceptions 表示可能被处理的条件。
package com.zetcode;
public class Main {
public static void main(String[] args) {
// Handling a checked exception
try {
throw new Exception("This is a regular exception");
} catch (Exception e) {
System.out.println("Caught Exception: " + e.getMessage());
}
// Attempting to handle an Error (not recommended)
try {
throw new OutOfMemoryError("This is an error");
} catch (Error e) {
System.out.println("Caught Error: " + e.getMessage());
}
// Uncaught Error will terminate the program
throw new StackOverflowError("This will terminate the program");
}
}
该示例表明,虽然 Errors 和 Exceptions 都可以被捕获,但 Errors 通常表示无法恢复的条件。 该程序尝试处理 OutOfMemoryError(在实践中不推荐),最后抛出一个未捕获的 StackOverflowError,从而终止执行。
来源
本教程介绍了 Throwable 类,它是 Java 错误处理的基础。 我们探讨了异常处理、自定义异常、链接、堆栈跟踪、抑制异常以及 Error/Exception 的区别。
作者
列出所有Java教程。