Java参数传递本质是值传递:基本类型在栈上复制数值,互不影响;引用类型传递地址值,栈存引用、堆存对象,修改对象属性影响全局,但重新赋值引用只改变当前栈帧指向。

Java 中参数传递的本质,是值传递,而栈和堆的变化取决于参数类型——基本类型走栈,引用类型“值”在栈、对象在堆。分析时抓住两点:实参怎么交出去,形参怎么接住,以及后续操作影响的是哪块内存。
基本类型参数:全程在栈上复制,互不干扰
int、boolean、double 等基本类型作为参数传入时,JVM 把实参的数值(比如 5)拷贝一份,压入新栈帧的局部变量表中。这个拷贝和原变量物理隔离:
- 形参修改(如 depth++)只改当前栈帧里的副本,不影响调用方的变量;
- 方法返回后,该栈帧弹出,副本自动消失,无需回退;
- 多个递归层级各自拥有独立的 depth 变量,它们共存于不同栈帧中,地址不同、生命周期不同。
引用类型参数:栈上存地址值,堆上存对象本体
传的是对象引用(如 TreeNode root),实际传递的是堆中对象的地址编号(比如 0x0034),这个地址值本身被拷贝到新栈帧里:
- 形参变量(如 root)是栈上的一个引用变量,它指向堆中同一个对象;
- 通过 root.left = new TreeNode() 修改对象属性,会影响堆中那个实例——因为多个栈帧的引用值都指向同一块堆内存;
- 但若在方法内让 root = null 或 root = new TreeNode(),只是改变了当前栈帧中这个引用变量的指向,不影响调用方栈帧里原来的引用值。
栈帧生命周期决定变量存亡,堆对象由 GC 接管
每次方法调用,JVM 在线程栈中分配一个栈帧;方法结束,栈帧立即弹出,其中所有局部变量(包括参数)全部销毁:
立即学习“Java免费学习笔记(深入)”;
- 栈帧增长对应方法调用,收缩对应方法返回,严格遵循 LIFO;
- 栈空间有限,递归过深会触发 StackOverflowError;
- 堆中的对象只要还有栈中引用变量指向它,就不会被回收;一旦所有引用消失(如方法结束且无其他变量持有),对象变成垃圾,等待 GC 清理。
典型误区:混淆“改对象”和“改引用”
常见错误是以为 root = root.left 这类赋值能改变上层调用者持有的引用。实际上:
- 这行代码只是把当前栈帧里的 root 变量从指向原节点,改为指向左子节点;
- 上层方法栈帧中的 root 引用仍保持原值,未受任何影响;
- 真正要“向上传递变化”,得靠 return 返回新引用,或修改对象内部状态(如 node.val = 100)。


















