Java中catch块的异常参数是JVM直接传递的原始异常对象引用,属引用传递;该对象在堆中唯一存在,携带完整栈轨迹,catch内操作均作用于原实例,重抛时亦复用同一对象以保障错误定位准确性。

Java中,当Exception对象作为catch块参数时,它不是被“复制”或“重新构造”的,而是由JVM直接将**已创建的异常实例引用**传递给catch块的形参。这个过程本质上是引用传递,而非值传递或深拷贝。
异常对象的来源与传递路径
异常对象在异常发生时由JVM即时创建(例如new NullPointerException()),并立即被抛出。该对象一旦生成,就存在于堆内存中,拥有唯一的身份(identity)和完整的堆栈跟踪(stack trace)。JVM在查找匹配catch块的过程中,并不修改或重建该对象,而是在找到对应catch后,把它的引用赋给catch括号中的形参变量(如catch (IOException e)中的e)。
- 形参
e只是该异常对象的一个局部引用,作用域仅限于当前catch块 - 你在catch块内调用
e.getMessage()、e.printStackTrace()等方法,操作的始终是原始异常实例 - 即使多个catch块按顺序排列,也只有一个会被执行,因此该引用只被一个形参接收一次
为什么不能在catch外访问try块的局部变量?
这和异常传递机制无关,而是作用域规则决定的:try块内声明的变量(如FileInputStream fis = new FileInputStream("a.txt");)属于try的作用域,对catch和finally不可见。但异常对象本身是JVM“主动送进来”的参数,不受该限制——它不是try块里定义的,而是运行时环境注入的。
多catch块中异常引用的独立性
每个catch块的形参都是独立声明的变量,即使类型相同(如两个catch (IOException e)),它们也各自持有对同一个异常对象的引用(前提是能匹配到同一异常)。但实际开发中不会写重复类型的catch,因为JVM只会进入第一个匹配的块,后面的同类型catch永远不会触发。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 子类异常优先匹配(如
FileNotFoundException先于IOException),确保捕获精度 - 所有catch形参共享原始异常对象的状态:修改其字段(极不推荐)会影响后续处理;但通常异常类字段是final的,不可变
与throw语句的呼应关系
当你在方法中写throw e;(在catch块内重抛),JVM不是新建异常,而是继续沿用这个原始对象,将其向调用栈上层传播。它的堆栈跟踪从最初抛出处开始,不会因catch或重抛而截断或重置——除非显式调用e.fillInStackTrace()。
这种设计保证了异常诊断信息的完整性:日志里看到的堆栈,永远指向问题最初发生的位置,而不是catch所在行。

















