提问人:Aman Kumar Sinha 提问时间:9/6/2022 最后编辑:Aman Kumar Sinha 更新时间:9/6/2022 访问量:63
澄清 Java 按值传递进行重新分级
Clarification regrading Java pass-by-value
问:
我正在解决一个编码问题,我们需要删除只有 0 作为其值的二叉树的所有子树。问题链接 https://leetcode.com/problems/binary-tree-pruning/ 对我有用的解决方案是这样的
public TreeNode pruneTree(TreeNode root) {
if (root == null)
return null;
root.left = pruneTree(root.left);
root.right = pruneTree(root.right);
if (root.val == 0 && root.left == null && root.right == null)
root = null;
else
return root;
// pruneTree1(root);
// printTree(root);
return root;
}
我之前尝试提交的解决方案是这样的
public TreeNode pruneTree(TreeNode root) {
pruneTree1(root);
return root;
}
TreeNode pruneTree1 (TreeNode root) {
if(root ==null)
return root ;
root.left = pruneTree1(root.left);
root.right = pruneTree1(root.right);
if(root.left==null && root.right==null && root.val==0) {
System.out.println(root.val);
root =null;
}
return root;
}
我的问题/疑问是为什么第二个解决方案没有改变原来的树。我的理解是 Java 是按值传递的,但是当我们通过变量名传递对象时,它是对原始对象的引用,我们可以更改其内容。
为什么在这种情况下不起作用。是因为我试图将整个对象设置为 null 而不仅仅是它的值吗?
我厌倦了用另一个例子重新创建场景,在这种情况下,代码的行为不同。这是我尝试过的
public void run1() {
TreeNode root = new TreeNode();
root.val = 2;
TreeNode left = new TreeNode();
left.val = 3;
TreeNode right = new TreeNode();
right.val = 4;
TreeNode leftLeft = new TreeNode();
leftLeft.val = 5;
TreeNode rightRight = new TreeNode();
rightRight.val = 6;
root.left = left;
root.right = right;
left.left = leftLeft;
right.right = rightRight;
System.out.println(root.left.left.val);
TreeNode root2 = makeNull(root);
System.out.println(root.left.left);
System.out.println(root2.left.left);
};
public TreeNode makeNull (TreeNode root){
if(root ==null)
return root ;
root.left = makeNull(root.left);
root.right = makeNull(root.right);
if(root.val==5)
root=null;
// left.left = null;
return root;
}
在示例中,当我打印它时,root.left.left 和 root2.left.left 都设置为 null。为什么它像参数一样,在这种情况下作为参考传递,但在上面的示例中没有。
答:
0赞
cyberbrain
9/6/2022
#1
在第二个示例中,您没有使用过 的结果。但是,该方法的参数从未为其调用方修改过(由于按值传递)。pruneTree1()
更新已添加示例:
root.left
并引用同一对象。因为你也不会改变这一点。root2.left
root.left.val != 5
您可以将 和 分配给方法的返回值,但在大多数情况下返回输入参数。所以只要你不返回,同样的对象仍然被引用。root.left
root.right
null
评论
0赞
Aman Kumar Sinha
9/6/2022
你是对的,这就是我的困惑所在.当我从 pruneTree1 返回(使用)返回对象时,该解决方案有效。但是为什么我需要使用返回的对象。为什么当 prune1 函数的参数(对象变量名称)是对原始对象的引用时,它不会更改原始树本身。@cyberbrain
1赞
cyberbrain
9/6/2022
你没有改变原来的树,这意味着你修改了 or 或 的值。您仅使用调用方不会将该更改视为参数的更改(因为是对对象的引用,该对象由值传递,因此调用方永远不会更改),而仅作为返回值。您可以将其视为调用方具有方法的所有参数的行为 - 这对于被调用方来说是不同的。root.val
root.left
root.right
root
root = null;
root
final
评论