澄清java传值

时间:2013-10-20 06:16:27

标签: java memory pass-by-reference

我很困惑为什么下面的代码不会改变Node 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是一个对象,它的引用是不是通过值传递给方法改变了?这意味着对传入的节点所做的任何更改都应该实际更改节点?

5 个答案:

答案 0 :(得分:3)

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

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

这个完全相同的代码可以使用,但没有介于两者之间的方法。

执行此操作a = a.next;而不是change(a),现在您的a.data2

答案 1 :(得分:0)

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

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

并将其命名为:

a = change(a);
System.out.print(a.data);

答案 2 :(得分: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

答案 3 :(得分: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;

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

答案 4 :(得分:-4)

请参阅Call by Value,了解参数的分配没有(也不会)改变调用者中的变量绑定的原因:

  

.. 在按值调用时,将计算参数表达式,并将结果值绑定到函数中的相应变量 .. 如果函数或过程能够要为其参数赋值,只有它的本地副本被分配 - 也就是说,[函数调用时用作参数的任何变量]在函数返回时在调用者的作用域中保持不变。

     

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


注意上面有意使用的不同术语变量,参数和参数。变异的对象在任何地方都会发生变化 - 这可以由Call by [Object] Sharing一致地描述;但是,这与Call by Value正交。