使用Java中的pass by值更新Tree节点

时间:2014-04-22 07:05:28

标签: java arraylist pass-by-reference pass-by-value

在我展示问题之前,我理解的是: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);
        }

    }
}

我在这里缺少什么,我很难在制作二叉树时更新根节点。

2 个答案:

答案 0 :(得分:1)

您的混淆来自于您错误解释按值调用的事实。

  

[...]内部函数make&#34; root = new_node;&#34;即=&gt;期望root的内存位置/地址更新为/指向&#34; new_node&#34;是[...]

这将完全描述 call-by-reference ,因为Java只会按值调用 - 不会发生。

您的第一个代码段与第二个代码段之间的主要区别在于:在第一个示例中,您通过为其指定新引用来重新初始化该参数。这不会反映在调用函数中。在第二个示例中,您将取消引用在此引用处处理对象的参数(&#34;。&#34;也称为取消引用运算符)。调用函数和被调用函数都具有相同的引用,因此在解除引用时它们都在同一个对象上工作。

查看Wikipedia article about call-by-value

答案 1 :(得分:1)

传入对方法的引用意味着引用是一个值。通过存储在堆栈上的方法参数root的名称,可以使用此值。为参数root分配不同的引用只会反映在方法内部,但是一旦离开方法,堆栈中的所有内容都将丢失。

您希望实现的是对变量my_root保留的值的修改。为此,您需要将引用传递给变量my_root,而不仅仅是my_root按住。例如,这可以通过传入保存对Node s的引用的容器来完成。 Java Collection是其中一个容器。传入容器并修改其值将反映在方法NodeModify(Node root)之外。

一些附注:

    Java中的
  • 方法应该以小写字母或下划线开头
  • 使用camel-case作为变量名而不是下划线来分隔单词,除非您定义常量