java一直是call by value,真的

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
*/

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/paulkg12/article/details/76795049