在我展示问题之前,我理解的是:Java使用传递值。
说,在下面的例子中,我将“my_root”引用传递给NodeModify(),
并且符合“NodeModify(my_root);”期望编译器传递“my_root”的内存地址副本和内部函数make“root = new_node;”即=>期望root的内存位置/地址更新为/指向“new_node”所在的位置。
令人惊讶的是,它没有反映在main()函数的调用位置,为什么会这样呢?
package com.trees;
public class NodeExample {
public static void NodeModify(Node root){
System.out.println("[NodeModify] fresh root is : " + root);
Node new_node = new Node(0);
System.out.println("[NodeModify] new node is : " + new_node);
root = new_node;
System.out.println("[NodeModify] root is : " + root);
}
public static void main(String[]arg){
Node my_root = new Node(55);
System.out.println("my root before NodeModify is: " + my_root);
NodeModify(my_root);
System.out.println("my root after NodeModify is: " + my_root);
}
}
但是,如果我对其他引用(如ArrayList)执行相同操作,则会按照我的预期在main()中进行更新! 示例:
package com.trees;
import java.util.ArrayList;
public class ArrayListUpdateClass {
public static void updateMyArrayList(ArrayList<String> sample){
sample.add("was updated!");
}
public static void main(String[]args){
ArrayList<String> my_list = new ArrayList<String>();
my_list.add("My list ");
System.out.println("**Before call list is:**");
printArrayList(my_list);
updateMyArrayList(my_list);
System.out.println("\n**After call list is:**");
printArrayList(my_list);
}
private static void printArrayList(ArrayList<String> my_list) {
for(String item:my_list){
System.out.println(item);
}
}
}
我在这里缺少什么,我很难在制作二叉树时更新根节点。
答案 0 :(得分:1)
您的混淆来自于您错误解释按值调用的事实。
[...]内部函数make&#34; root = new_node;&#34;即=&gt;期望root的内存位置/地址更新为/指向&#34; new_node&#34;是[...]
这将完全描述 call-by-reference ,因为Java只会按值调用 - 不会发生。
您的第一个代码段与第二个代码段之间的主要区别在于:在第一个示例中,您通过为其指定新引用来重新初始化该参数。这不会反映在调用函数中。在第二个示例中,您将取消引用在此引用处处理对象的参数(&#34;。&#34;也称为取消引用运算符)。调用函数和被调用函数都具有相同的引用,因此在解除引用时它们都在同一个对象上工作。
答案 1 :(得分:1)
传入对方法的引用意味着引用是一个值。通过存储在堆栈上的方法参数root
的名称,可以使用此值。为参数root
分配不同的引用只会反映在方法内部,但是一旦离开方法,堆栈中的所有内容都将丢失。
您希望实现的是对变量my_root
保留的值的修改。为此,您需要将引用传递给变量my_root
,而不仅仅是my_root
按住值。例如,这可以通过传入保存对Node
s的引用的容器来完成。 Java Collection
是其中一个容器。传入容器并修改其值将反映在方法NodeModify(Node root)
之外。
一些附注: