关于java传递值的说明

Posted

技术标签:

【中文标题】关于java传递值的说明【英文标题】:Clarification on java pass-by-value 【发布时间】:2013-10-28 18:18:06 【问题描述】:

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

public class NodeNode 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是一个对象,那么它的引用不是按值传递给方法的吗?这意味着对传入的节点所做的任何更改实际上都应该更改节点?

【问题讨论】:

我确定有一两个重复的 [一百] .. 像 ***.com/questions/40480/… 或 ***.com/questions/7893492/… (上面的代码精确地不起作用,因为Java是Call by Value - 重新分配参数影响变量/绑定来电者。) 我正在尝试理解在 java 中传递的参数,而不是真正尝试实现某些功能 【参考方案1】:

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

.. 在按值调用中,计算参数表达式,并将结果值绑定到函数中的相应变量 .. 如果函数或过程能够为了给它的参数赋值,只赋值它的本地副本——也就是说,当函数返回时,[用作参数的任何变量]函数调用在调用者的范围内都不会改变

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


注意上面有意使用的不同术语变量、参数和参数。一个发生变异的object,嗯,到处都发生了变化——Call by [Object] Sharing 始终如一地描述了这一点;然而,这与按值调用是正交的。

【讨论】:

我不知道为什么人们在没有 cmets 的情况下投反对票。这是一个明智的答案,尤其是。在提到“通过共享调用”【参考方案2】:

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

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

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

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

【讨论】:

"创建一个引用的副本到一个“编号a一个引用(它是一个引用类型的变量)。不能有“对a 的引用”。 @newacct 我认为很明显我的意思是对内存中对象的引用,人类将其称为a,而不是对引用的引用......但我编辑了它并删除了“to”。【参考方案3】:

运算符 = 更改“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

【讨论】:

【参考方案4】:

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,因为正如我之前在 change 方法中所说的 a 是一个新变量!

【讨论】:

【参考方案5】:

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

public static Node change(Node a)

return a.next;

然后调用它:

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

【讨论】:

以上是关于关于java传递值的说明的主要内容,如果未能解决你的问题,请参考以下文章

关于Java函数不支持参数默认值的讨论,最后一条亮了 2333

关于java中值传递还是引用传递

关于java通过方法调用传递一个数组的疑问

JAVA语言中 有返回值的方法和无返回值的方法有啥区别啊 请举例子说明!!

关于java数据表搜索 列值的返回问题

关于java中属性变量默认值的问题。