java一直是call by value,真的

xiaoxiao2021-02-28  104

java 一直是值传递

这是一篇译文,原文:

https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

如果你看不完,或者看不懂,请直接看后记的结论。

问题描述:

我过去一直以为 java 是pass-by-reference但是我见了一个帖子说不是的。我觉得自己不明白其中的区别,解释是什么?

回答如下:

请记住 java 一直是值传递 。

但是很不幸,他们决定把一个对象的地址称为reference.实际上我们可以这样说:

当我们把一个对象的值传递过去的时候,我们其实就是在传递它的引用(reference)

大概可能对初学者, 这一点让他们会感到困惑

来吧,我们来一起看看:

public static void main( String[] args ) { Dog aDog = new Dog("Max"); // we pass the object to foo foo(aDog); // aDog variable is still pointing to the "Max" dog when foo(...) returns aDog.getName().equals("Max"); // true, java passes by value aDog.getName().equals("Fifi"); // false } public static void foo(Dog d) { d.getName().equals("Max"); // true // change d inside of foo() to point to a new Dog instance "Fifi" d = new Dog("Fifi"); d.getName().equals("Fifi"); // true }

在这个例子里,aDog.getName()将会仍旧返回"Max".

在main里的aDog没有被foo()函数改变。要是是call-by-reference的话,我们应该能够预见,在调用foo()后,aDog.getName()应该返回Fifi。而实际上,并没有。

同样地:

public static void main( String[] args ) { Dog aDog = new Dog("Max"); foo(aDog); // when foo(...) returns, the name of the dog has been changed to "Fifi" aDog.getName().equals("Fifi"); // true } public static void foo(Dog d) { d.getName().equals("Max"); // true // this changes the name of d to be "Fifi" d.setName("Fifi"); }

在上面的例子中,Fifi就是在调用foo()后,狗的名字了。因为对象的名字被设置成了Fifi。

再举出最后一个例子:

public void test() { MyClass obj = null; init(obj); //After calling init method, obj still points to null //this is because obj is passed as value and not as reference. //在调用init方法后,obj仍旧指向空 //这是因为,obj是值传递,而不是引用传递。 } private void init(MyClass objVar) { objVar = new MyClass(); }

最后一句话:

In Java only references are passed and are passed by value

java中只有引用被传递了,而且是以值传递的方式

后记(20181030)

我回头看自己的文章都不知道写的啥意思,所以我又做了一次检验。我把结论说明白

结论:

你传进去函数的值(比如a)只是一个寻址的钩子,钩子的指向(也就是这个值)可以改变(比如改变成b,c,d…),当你在子函数中玩完,退出了,你钩子指向的变更,都是无效的。

外层函数继续它的一切时,会发现钩子的a值 曾经 被传递到子函数中,但是无论子函数对这个值(a)怎么变更(比如:a=b),回到主函数我这里 ,a还是a

总结(20181109)

当子函数内,令这个引用去指向新的内存了(by new 关键字),那么我们现在对同名的那个原来的引用,其实已经是指向新的内存地址(对应着一个新的对象),我们现在对引用的任何操作,都无法影响原来的那个引用了。 当子函数内,直接调用这个原引用的一些内置行为,改变了其属性,那么现在是确实地改变了其属性。

Java 是传递的引用,一个引用: 你可以理解为一个内存地址,一个容器,装着对象的实例,每个容器都有个名字,也就是我们声明变量时,给变量的那个名字。

那么,1》如果我们不赋新的(内存,引用)值,那么一切都好好的, 我们改了对象的什么,就真的改了,2》如果有新的值赋值给原引用,那么其实是子函数局部的这个容器装了一个新的内存地址,aka 新的引用,而对新的容器的任何变更,将不会影响到原容器。

范例:

public class RefTest { public static void main(String[] args) { TreeNode bNode = new TreeNode(null, null, 2); TreeNode cNode = new TreeNode(null, null, 3); TreeNode aNode = new TreeNode(bNode, cNode, 1); addressing(aNode);// System.out.println("a is new 3???" + aNode.val); } public static void addressing(TreeNode root) { root = root.right; } } class TreeNode { TreeNode left; TreeNode right; int val; TreeNode(TreeNode left, TreeNode right, int val) { this.left = left; this.right = right; this.val = val; } } /*output : a is new 3???1 the reference you are getting is a value reference that if overwritten will be restored when exiting the function. 你传进去函数的值(比如a)只是一个寻址的钩子,钩子的指向(也就是这个值)可以改变(比如改变成b,c,d...),当你在子函数中玩完,退出了,你钩子指向的变更,都是无效的。 外层函数继续它的一切时,会发现钩子的a值 *曾经* 被传递到子函数中,但是无论子函数对这个值(a)怎么变更(a=b),回到主函数我这里 , a还是a */

转载请注明原文地址: https://www.6miu.com/read-65768.html

最新回复(0)