package ztest; public class Test { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person(); p1.setName("name1"); p2.setName("name2"); System.out.println(p1+" <-- 原始的 p1"); System.out.println(p2+" <-- 原始的 p2"); convert(p1, p2); System.out.println(p1+" <-- 调用方法后的 p1"); System.out.println(p2+" <-- 调用方法后的 p2"); p1 = p2; System.out.println(p1+" <-- 赋值后的 p1"); System.out.println(p2+" <-- 增值后的 p2"); } public static void convert(Person a, Person b) { a = b; System.out.println(a+" <-- p1 in method"); System.out.println(b+" <-- p2 in method"); } } class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
ztest.Person@2a139a55 <-- 原始的 p1 ztest.Person@15db9742 <-- 原始的 p2 ztest.Person@15db9742 <-- p1 in method ztest.Person@15db9742 <-- p2 in method ztest.Person@2a139a55 <-- 调用方法后的 p1 ztest.Person@15db9742 <-- 调用方法后的 p2 ztest.Person@15db9742 <-- 赋值后的 p1 ztest.Person@15db9742 <-- 增值后的 p2
从输入出结果可以看到在方法体内进行 p1=p2后 ,p1确实改变了. 但是出了方法体p1还是原始的p1. 那么在Java方法调用中,对象做为参数传递的肯定不是p1的引用.
那么我们可以认为实际上在调用方法时 p1有一个影子 p1' . 这个p1'与p1指向的都是堆区上的同一个对象. p1做为对象传递时其实是传的p1',这样就可以合理的解释在方法里内改变p1的属性值是可行的.而直接对p1赋值实际上改变的是p1' 的引用,对p1本身没有影响.
再来看,如果出了方法体再进行p1=p2; 此时p1的引用会被p2覆盖,p1与p2都指向了 原始p2所在堆上的内存块.