在Java中,将基本数据数据类型或对象传递给一个方法,我们通常会说一个是值传递,一个是引用传递,但是真的是这样吗?
其实这种说法是错误的,在Java中,所有都是严格的值传递。
疑问
假设有下面一串代码,两个类Foo和Dog,在Foo类的方法中,操作Dog类
class Foo { public static void main(String[] args) { Dog a = new Dog(); a.setName("狗1号"); System.out.println(a.getName()); new Foo().setDog(a); System.out.println(a.getName()); } public void setDog(Dog b) { b = new Dog(); b.setName("狗2号"); } } class Dog { private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
上面代码的执行结果为:
狗1号 狗1号
如果按照引用传递的说法来解释,在Foo类中的setDog方法传递的Dog dog是引用,那为什么更改了引用,改为狗2号,在main方法第二次打印的却还是狗1号呢?
解释
Dog dog = new Dog(); dog.setName("狗1号");
当代码执行到这里时,我们初始化了一只名字叫做狗1号的Dog对象。

new Foo().setDog(a);
当代码执行调用方法时,问题就在这里,这里将a变量传入到方法setDog,发生的是值传递还是引用传递呢?
这里是值传递,这个值,指的是引用值(指针或者内存值)。
变量a是个引用,有个引用值,指向存在内存里的对象,这样才能正确的操作狗1号对象。
执行setDog方法时,Java将变量a的引用值,复制一份给了变量b(值传递给了变量b),所以变量b也可以操作狗1号对象。

public void setDog(Dog b) { b = new Dog(); b.setName("狗2号"); }
代码继续执行,执行方法块里的代码,注意此时有一个b = new Dog();的操作,此操作会将变量b的引用值改变,也就是说此时变量b和a指向的不再内存里同一个Dog对象。

到这里也就能说明问题了,Java中是不存在引用传递的,因为如果变量b是引用传递,那b改变了引用指向的对象,那变量a也应该改变执行的对象,这样才是引用传递。而如果变量b是值传递,就可以解释,为什么在setDog()方法执行过后,变量a还是指向原来的对象。
我上面解释的可能也不是很清晰明了,大家可以看下面的网址,讲的更清楚。