在Java中,如果我在递归调用期间更改对象引用,它是否会传播?

时间:2012-09-30 14:32:47

标签: java recursion

例如,我进行下面定义的递归调用。该方法从最后一个中找到第k个元素。如果找到,它会将当前节点分配给我传递给递归调用的对象。由于某种原因,节点kth为空。你不能这样做吗?为什么?

public void findKthFromLast(Node head, int k){
    Node kth;     
    recrusiveHelper(head, k, kth);
    System.out.println(kth.data); //this is null
}

public int recursiveHelper(Node n, int k, Node kthFromLast){
    (if n == null){
        return 0;
    }
    val = 1 + recursiveHelper(n.next, k, kthFromlast);
    if(k == val){
        kthFromLast = n;
    }
    return val;
}

3 个答案:

答案 0 :(得分:3)

如果对象引用是方法的本地对象,则调用方或其他任何人都无法看到对它的更改。

E.g:

void caller()
{
    obj = new String("asdf");
    doStuff(obj)
    System.out.println(obj) // still prints "asdf"
}

void doStuff(String obj)
{  
   // obj is a local reference, changing it wont affect caller's ref 
   obj = new String("ghj");
}

答案 1 :(得分:2)

首先,该代码不应编译,因为kth未初始化,因此不能用作recursiveHelper方法调用的参数。

其次,对被调用方法中引用的任何更改都不会传播给Java中的调用者,即

private void caller()
{
    StringBuilder s = new StringBuilder();
    s.append("test");
    calledMethod1(s);
    System.out.println(s.toString());
    calledMethod2(s);
    System.out.println(s.toString());
}

private void calledMethod1(StringBuilder buffer)
{
    buffer = new StringBuilder();
    buffer.append("calledMethod1");
    return;
}

private void calledMethod2(StringBuilder buffer)
{
    buffer.append(", calledMethod2");
    return;
}

输出:

test
test, calledMethod2

原因是,在calledMethod1中,您只是更改了buffer引用指向的内容,但没有对调用该方法时buffer引用指向的内容进行任何更改。在calledMethod2中,您正在对buffer引用的对象进行更改,因此更改在调用方中可见。

如果您是来自CC++背景的人,这相当于在被调用方法中指定一个指针参数,该参数不会影响调用者传递的内容。

答案 2 :(得分:0)

public void findKthFromLast(Node head, int k){
    Node kth;     
    recrusiveHelper(head, k, kth);
    System.out.println(kth.data); //this is null
}

您将null传递给该方法,无论您在该方法中执行什么操作,在此之外将保持为null。您无法以在方法之外可见的方式更改引用值。