简体   繁体   English

对Java传递值的澄清

[英]Clarification on java pass-by-value

I'm confused as to why the following code doesn't change the data of the Node a: 我对以下代码为什么不更改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?
}

Since Node is an object, isn't its reference passed by value to the method change? 由于Node是一个对象,它的引用不是通过值传递给方法更改吗? Which means any changes made to the passed in Node should actually change the node? 这意味着对传入的Node所做的任何更改实际上都应该更改该节点?

This is because in Java you call methods via reference-copies. 这是因为在Java中,您是通过引用副本调用方法的。

This means that when you call change(a); 这意味着当您调用change(a); Java basically creates a copy of the reference a and this will be the incoming parameter in public static void change(Node a) . Java基本上会创建引用a的副本,这将是public static void change(Node a)的传入参数。 Inside the method you will then change that copied reference to point somewhere else. 然后,在方法内部,您将更改复制的引用以指向其他位置。 And this will have no effect once your method returns. 一旦您的方法返回,这将无效。

This exact same code will work though without the method in between. 尽管之间没有方法,但此完全相同的代码将起作用。

Do this a = a.next; 这样做a = a.next; instead of change(a) and now your a.data will be 2 . 而不是change(a) ,现在您的a.data将是2

Your change method does an empty assignment. 您的更改方法将执行空的分配。 The variable a is set to the next node but not returned from the method. 变量a设置为下一个节点,但未从方法返回。 The change will only be available inside the method scope. 更改将仅在方法范围内可用。 You could change that: 您可以更改:

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

And call it with: 并调用:

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

The operator = change the reference of "a". 运算符=更改“ a”的参考。 Use a method "set(Node nodeToCopy)" That will copy all the "nodeToCopy" in the current node. 使用方法“ 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);
}

BUT !!! 但是! It not that you want to do because, it will break your objects a and b. 这不是您要执行的操作,因为它会破坏对象a和b。 You have no others solution : 您没有其他解决方案:

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

With

public static void change(Node a)

a is not an alias but a new variable containing the address of the paramerter passed.. a 不是 alias而是一个新变量,其中包含传递的参数的地址。

So, 所以,

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

But when you do 但是当你这样做

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

you are assigning the address of b which won't change the original Node a since as I said earlier a in change method is a new variable! 您正在分配b的地址,该地址将不会更改原始Node a因为正如我之前所说a in in change方法是一个新变量!

Refer to Call by Value for why the assignment to the parameter did not (and will not) alter the variable bindings in the caller: 请参阅按值调用,以了解为何对参数的赋值没有(也不会)改变调用者中的变量绑定的原因:

.. In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function .. If the function or procedure is able to assign values to its parameters, only its local copy is assigned - that is, [any variable used as an argument for] a function call is unchanged in the caller's scope when the function returns . .. 在按值调用中,对参数表达式进行求值,并将结果值绑定到函数中的相应变量 .. 如果函数或过程能够为其参数分配值,则仅分配其本地副本-即,当函数返回时,[用作函数调用参数的任何变量在调用者的范围内都是不变的

Call-by-value is not a single evaluation strategy, but rather the family of evaluation strategies in which a function's argument is evaluated before being passed to the function .. 按值调用不是一个单独的评估策略,而是一系列评估策略,其中在将函数的参数传递给函数之前先对其进行评估


Pay attention to the different terms variable, arguments, and parameter above which have been purposefully used. 请注意上面有意使用的不同术语变量,参数和参数 An object that is mutated is, well, changed everywhere - which is consistently describable by Call by [Object] Sharing ; 可以很容易地在任何地方更改被更改的对象 - 通过[Object] Sharing的调用可以始终描述该对象 this, however, is orthogonal to Call by Value. 但是,这与按值调用正交。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM