2

我很困惑为什么以下代码不会更改节点 a 的数据:

public class Node{Node next; int data;}
public static void change(Node a)
{
a = a.next;
}

public static void main(String [] args){

Node a = new Node();
Node b = new Node();
a.next = b;
a.data = 1;
b.next = null;
b.data = 2;
change(a);
System.out.print(a.data); //Still 1, why isn't it changed to 2?
}

既然 Node 是一个对象,那么它的引用不是按值传递给方法的吗?这意味着对传入的节点所做的任何更改实际上都应该更改节点?

4

5 回答 5

3

这是因为在 Java 中,您通过引用副本调用方法。

这意味着当您调用change(a);Java 时,基本上会创建引用的副本,a这将是public static void change(Node a). 在方法内部,您将更改复制的引用以指向其他地方。一旦您的方法返回,这将无效。

尽管没有中间的方法,但这个完全相同的代码也可以工作。

这样做a = a.next;而不是change(a)现在你的a.data意志是2

于 2013-10-20T06:20:43.593 回答
0

您的更改方法执行空任务。该变量a设置为下一个节点,但不从方法返回。更改将仅在方法范围内可用。你可以改变它:

public static Node change(Node a)
{
return a.next;
}

并调用它:

a = change(a);
System.out.print(a.data);
于 2013-10-20T06:22:52.103 回答
0

运算符 = 更改“a”的引用。使用方法“set(Node nodeToCopy)”将复制当前节点中的所有“nodeToCopy”。

public class Node{
Node next; 
int data;
public void set(Node Other) {
next = other.next;
data = other.data;
}
}


public static void change(Node a)
{
a.set(a.next);
}

但 !!!这不是您想要做的,因为它会破坏您的对象 a 和 b。您没有其他解决方案:

Node a = new Node();
Node b = new Node();
Node i = a;
a.next = b;
a.data = 1;
b.next = null;
b.data = 2;
System.out.print(i.data); //it's 1
i = i.next;
System.out.print(i.data); //it's 2
于 2013-10-20T06:29:24.733 回答
0

public static void change(Node a)

a不是一个,alias而是一个包含传递参数地址的新变量。

所以,

a.data=100;//would change value of the actual Node in main
[NewVariableWithAddressOfa].data=100;

但是当你这样做时

a = a.next;
[NewVariableWithAddressOfa]=[NewVariableWithAddressOfa].next;

您正在分配 b 的地址,它不会改变原始节点,因为正如我之前在方法中a所说的那样,它是一个新变量!achange

于 2013-10-20T06:29:42.833 回答
-4

请参阅按值调用,了解为什么对参数的赋值没有(也不会)改变调用者中的变量绑定:

..在按值调用中,对参数表达式进行求值,并将结果值绑定到函数中的相应变量..如果函数或过程能够为其参数赋值,则仅分配其本地副本- 也就是说,当函数返回时,[用作参数的任何变量] 函数调用在调用者的作用域内保持不变

按值调用不是单一的评估策略,而是一系列评估策略,其中函数的参数在传递给函数之前进行评估..


请注意上面有意使用的不同术语变量、参数和参数。一个发生变异的对象,嗯,到处都是变化的——这可以用Call by [Object] Sharing 来描述;然而,这与按值调用是正交的。

于 2013-10-20T06:32:16.373 回答