是的,Java中所有异常都是Throwable的实例。它们是运行时堆上的对象,可被创建、传递、捕获、检查和序列化;只有继承Throwable的类才能被throw或catch;Exception和Error是其直接子类,自定义异常必须继承其中之一。

是的,Java 中所有异常都是 Throwable 的实例,也就是实实在在的对象——它们可以被创建、传递、捕获、检查,甚至序列化。
为什么说异常是对象?从 throw 和 catch 看本质
Java 规定:只有继承自 Throwable 的类才能被 throw;而 catch 捕获的也必然是 Throwable 或其子类的引用。这说明异常不是语法标记或状态码,而是运行时堆上的对象。
常见误操作:
- 试图
throw null—— 会抛出NullPointerException(因为 JVM 要求必须是Throwable实例) - 写
catch (Exception e)却以为捕获的是“错误类型”,其实捕获的是一个指向堆中异常对象的引用 - 在
catch块里修改e.getMessage()并不改变原异常对象(除非是可变字段,但标准异常类基本不可变)
Exception 和 Error 都是 Throwable 的直接子类
Java 异常体系顶端是 Throwable,它有两个直接子类:
立即学习“Java免费学习笔记(深入)”;
-
Exception:程序本应捕获或声明的异常,比如IOException、SQLException -
Error:JVM 无法恢复的严重问题,如OutOfMemoryError、StackOverflowError,通常不应被捕获(捕获了也难以处理)
注意:RuntimeException 是 Exception 的子类,但它属于“未检查异常”(unchecked),编译器不强制要求 try-catch 或 throws;而 IOException 这类“检查异常”(checked)必须显式处理。
自定义异常必须继承 Throwable 或其子类
不能凭空写个类就 throw,否则编译失败。正确方式是继承 Exception(检查异常)或 RuntimeException(未检查异常):
public class InsufficientBalanceException extends RuntimeException {
public InsufficientBalanceException(String message) {
super(message);
}
}
关键点:
- 继承
RuntimeException→ 调用方无需try-catch或throws - 继承
Exception→ 编译器强制调用方处理,适合业务上必须响应的异常(如文件不存在) - 所有异常类默认都有无参构造和
String构造,建议至少提供这两种构造方法 - 不要重写
fillInStackTrace()除非有特殊性能需求(它开销较大)
真正容易被忽略的,是异常对象的生命周期和内存行为:每次 new XXXException() 都会在堆上分配对象,频繁抛异常(尤其在循环里)会显著影响性能;另外,异常的栈轨迹(printStackTrace() 输出的内容)是在构造时通过 fillInStackTrace() 收集的,这个过程本身就有开销。








