
java 所有参数均按值传递,包括对象引用;方法内对引用变量的重新赋值(如 entry = new simpleentry(...))仅改变局部副本,不影响调用方原始引用。
java 所有参数均按值传递,包括对象引用;方法内对引用变量的重新赋值(如 entry = new simpleentry(...))仅改变局部副本,不影响调用方原始引用。
在 Java 中,不存在真正的“按引用传递”——无论是基本类型还是对象,参数传递始终是“按值传递”。对于对象(如 Map.Entry
- ✅ 你可以通过该引用修改对象内部状态(例如调用 setValue() 修改已有 SimpleEntry 的值);
- ❌ 但你无法通过重新赋值引用变量(如 entry = new SimpleEntry(...))让调用方看到新对象——因为这只是修改了栈帧内的局部变量,原引用仍指向旧对象(或 null)。
回到你的 DFS 示例:
private void dfsHelper(TreeNode root, int level, Map.Entry<integer integer> deepestLevelSum) {
if (root.left == null && root.right == null) {
if (deepestLevelSum == null || deepestLevelSum.getKey() <p>当执行 deepestLevelSum = new ... 时,你只是把方法栈里的局部变量 deepestLevelSum 指向了一个新对象,而 deepestLeavesSum 在 deepestLeavesSum() 方法中的变量仍保持原值(初始的 (0, root.val)),因此最终 return deepestLevelSum.getValue() 返回的是初始值,而非更新后的结果。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0"><img
src="https://img.php.cn/upload/manual/001/431/639/6ad9ce71d8cb6379.png" alt="Gradle 9.8.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0" class="overflowclass">Gradle 9.8.0</a>
<p class="overflowclass"></p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2870" title="Gradle 9.8.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<h3>✅ 正确做法:统一使用可变容器或返回值</h3>
<h4>方案 1:使用数组包装(轻量、简洁)</h4>
<pre class="brush:php;toolbar:false;">public int deepestLeavesSum(TreeNode root) {
if (root.left == null && root.right == null) return root.val;
int[] result = {0, 0}; // [maxLevel, sum]
dfsHelper(root, 0, result);
return result[1];
}
private void dfsHelper(TreeNode root, int level, int[] res) {
if (root.left == null && root.right == null) {
if (level > res[0]) {
res[0] = level;
res[1] = root.val;
} else if (level == res[0]) {
res[1] += root.val;
}
} else {
if (root.left != null) dfsHelper(root.left, level + 1, res);
if (root.right != null) dfsHelper(root.right, level + 1, res);
}
}
方案 2:封装为自定义可变类(语义清晰)
static class LevelSum {
int maxLevel = -1;
int sum = 0;
}
// 调用时传入 new LevelSum(),方法内直接修改字段即可
方案 3:函数式返回(推荐,更符合 Java 习惯)
避免共享状态,让递归返回关键信息:
public int deepestLeavesSum(TreeNode root) {
return dfs(root, 0).sum;
}
private Result dfs(TreeNode node, int level) {
if (node == null) return new Result(-1, 0); // invalid level
if (node.left == null && node.right == null)
return new Result(level, node.val);
Result left = dfs(node.left, level + 1);
Result right = dfs(node.right, level + 1);
if (left.level == right.level)
return new Result(left.level, left.sum + right.sum);
return left.level > right.level ? left : right;
}
static class Result {
final int level, sum;
Result(int level, int sum) { this.level = level; this.sum = sum; }
}
? 关键总结
- Java 没有引用传递,只有引用的值传递;
- 修改对象属性(setValue())有效,重赋引用(=)无效;
- 避免依赖“传引用修改地址”的思维,优先选用不可变返回、数组/容器包装或类封装;
- 全局字段虽能工作,但破坏封装性与线程安全性,应尽量避免。
理解这一机制,是写出健壮、可维护 Java 递归代码的基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










