理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]
Posted
技术标签:
【中文标题】理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]【英文标题】:Understanding references in Java; addNode() function for BST is not behaving as it should [duplicate] 【发布时间】:2021-12-25 07:00:09 【问题描述】:我试图了解为什么我的第一个实现 addToTree()
不起作用,但第二个实现。我已经评论了不同的行:
public static void addToTree(Node n, int value) //return type is void
if (n != null)
if (n.val >= value)
addToTree(n.left, value);
else
addToTree(n.right, value);
else
n = new Node(value);
这是实际有效的实现:
public static Node addToTree(Node n, int value) //return type is Node
if (n != null)
if (n.val >= value)
n.left = addToTree(n.left, value); //sets n.left with the return value
else
n.right = addToTree(n.right, value); //sets n.right with the return value
else
n = new Node(value);
return n; //returns the new node after creating (adding) it
return n;
为什么我必须将n.right
和n.left
设置为addToTree()
的返回值?我不明白为什么 void 函数在这里不起作用以及为什么必须返回新节点。这是否解释了 Java 的“按值传递”性质?调用addToTree(n.left, value)
时,是不是没有传递对n.left
的引用?
【问题讨论】:
【参考方案1】:简答:Java 是按值传递,而不是按引用传递
长答案:由于 Java 是按值传递的,因此在方法中传递的任何值都将首先复制到内存中的不同位置,然后将该位置传递给方法。并且当方法更改值时,新(即复制)位置的值将更改,原始副本保持不变。
在原始值的情况下,只有值被复制到新位置,但在引用类型的情况下,传递给方法的值也会被复制,但由于它们是对其他位置的引用,所以引用的位置指向的仍然是一样的。
在你的情况下,当你在下一次递归调用中传递 n.left/right 时,引用被复制到不同的位置,最后一次递归调用在那个不同的位置写了n=new Node(value);
,但实际的 node.left/ right 保持不变。
当您看到引用类型作为按值传递时,我知道这一切都令人困惑。理解为什么将两个整数传递给交换方法不起作用,但传递一个包含两个元素的数组,并在 Java 中交换数组中的值。概念基本相同。查看此链接了解更多信息:Java: Why does this swap method not work?
【讨论】:
【参考方案2】:第一个实现的问题是,您创建的新节点被分配给n
,但随后n
立即超出范围并且对该节点的引用丢失。
当您声明方法参数Node n
时,您定义的变量n
类型为Node
,其范围仅限于此方法。当您调用该方法并传递像addToTree( myNode, myValue )
这样的参数时,方法内部的变量n
被分配myNode
,就像分配n = myNode
。在您的方法结束时,您为n
分配一个新值。这类似于做这样的事情:
Node myNode = new Node( 7 );
Node n = myNode; // Now n points to the same object as myNode
...
n = new Node( 10 ); // Now n points to a different object
您是否希望 myNode
现在的值为 10?不,因为这两个变量指向不同的对象。在您的方法中,变量n
被分配了一个带有value
的新节点,但是一旦您的方法结束,n
的范围就会结束并且对您的新节点的引用消失。
所以基本上你创建了一个新节点,然后你立即失去它。您必须从您的方法中返回该新节点,以便有人可以将其保存在树中的某个位置。在您更改的其他行中,您将该新节点保存在树中,例如n.left = addToTree( n.left, value )
。这将获取方法调用的结果,该结果将是新创建的节点,并将其存储在节点 n
的左侧。
【讨论】:
以上是关于理解 Java 中的引用; BST 的 addNode() 函数未按应有的方式运行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章