Java的引用传递和值传递

2017-05-17  本文已影响0人  假鞋子

首先,Java中并不存在指针,但有类似的现象,叫“引用传递”。
一部分人觉得java中存在【引用传递】和【值传递】,而也有一部分人认为java中只存在【值传递】。他们表达的意思是一样的,却是从两个方面来表达。
首先java中的确存在两种情况。下面来看一个例子;

public class Test {
    public static void change(int a){
        a=50;
    }
    public static void main(String[] args) {
        int a=10;
        System.out.println(a);
        change(a);
        System.out.println(a);
    }
}

输出:10,10
可见change方法并没有改变main中的a的值。
这里传递到change中的a是一个拷贝,对原来的值不产生影响。


再看:

public class Test3 {
    public static void change(int []a){
        a[0]=50;
    }
    public static void main(String[] args) {
        int[] a={10,20};
        System.out.println(a[0]);
        change(a);
        System.out.println(a[0]);
    }
}

输出:10,50;
可见这里的change方法改变了main中的a,
这里传递到change中的a是一个地址的值,指向原来的值。

<br />

深入


我们来看下面的例子:

作者:Intopass
链接:https://www.zhihu.com/question/31203609/answer/50992895
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

第一个例子:基本类型
void foo(int value) {
    value = 100;
}
foo(num); // num 没有被改变

第二个例子:没有提供改变自身方法的引用类型
void foo(String text) {
    text = "windows";
}
foo(str); // str 也没有被改变,也因为每一个"xxx"都是一个新的对象

第三个例子:提供了改变自身方法的引用类型
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder.append("4");
}
foo(sb); // sb 被改变了,变成了"iphone4"。

第四个例子:提供了改变自身方法的引用类型,但是不使用,而是使用赋值运算符。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder = new StringBuilder("ipad");
}
foo(sb); // sb 没有被改变,还是 "iphone"。

这里有些人可能对图四难以理解,为什么foo方法中对传入的sb做了赋值,但是sb还是没有改变呢?
那我们再来看看下面的例子和相应的内存模型:

public static void main(String[] args) {
    Demo d1 = new Demo();
    fun(d1);
);
}
public void fun(Demo d2){
    xxxx;
}
d1、d2内存模型

这里我们发现,当调用fun方法的时候,栈内存中出现了d2值,指向了d1指向的空间。
这也就解释了上面第四个例子:当调用foo方法传入d1时,实际上是在栈内存中新增了d2值,同时d2指向d1指向的堆内存空间。当foo方法内部进行新的【赋值】操作时,实际上改变了的是d2的指向,并不会改变d1的值。

这里我们需要注意的一点是d2的赋值是改变其指向的位置。而不是改变指向位置的值。

上一篇 下一篇

猜你喜欢

热点阅读