先来看个有意思的题目:



1 public class Test {
 2     public static void main(String args[]){
 3         StringBuilder test = new StringBuilder("aa");
 4         Change(test);
 5         System.out.println(test.toString());
 6     }
 7 
 8     private static void Change(StringBuilder test) {
 9         test = new StringBuilder("bb");        
10     }
11 }



这里的输出是多少呢?对,输出为:aa          ^_^
再看一个题目:



1 public class Test {
 2     public static void main(String args[]){
 3         Person test = new Person();
 4         test.setId(123);
 5         Change(test);
 6         System.out.println(test.getId());
 7     }
 8 
 9     private static void Change(Person test) {
10         test.setId(456);        
11     }
12 }



这里的输出又是多少呢?对啦,就是:456           ^_^
还有一个:



1 public class Test {
 2     public static void main(String args[]){
 3         Person test = new Person();
 4         test.setId(123);
 5         Person newTest = test;
 6         Change(test);
 7         System.out.println(newTest.getId());
 8     }
 9 
10     private static void Change(Person test) {
11         test.setId(456);        
12     }
13 }



这里的输出又是多少呢?还是:456      ^_^
看了上面几个小题目,可能有点同学就要说太easy,简直是小case,拿这种题来考我,嘛意思吗!!!
其实真正知道并能说出来龙去脉的,我问了我周围的同学,都是“就是这样嘛,……”,“知道结果不久完了吗……”
看来还是有不少同学对java中参数的问题含含糊糊的哦。

在java中,只要我们在传参时把握:"对象传引用,基本类型传值",就能解释上面的问题了。

在第1题中,test被初始化为StringBuilder对象实例的引用,test为一个引用,指向"aa",下一行,调用了方法change(StringBuilder test),这时test作为change()方法参数,被传递到方法中,在change()方法中,将传进来的参数指向了一个新的对象实例StringBuilder("bb"),即test-->"bb",但是并没有改变原来的对象"aa",在change()方法结束后也没有返回修改,故在change()中的参数随着方法结束就被释放了(相当于外派人员test干了一些老板"aa"不知道的事,没有报告给老板,故不会涨工资),此时作为main()方法的参数,test还是有效的引用,即指向"aa"的引用,所以打印出来的结果是aa。

在第2题中,test被初始化为Person对象实例的引用,并修改这个实例id的值为123,下一行,调用change(Person test)方法,test被作为实参传递到方法中,并对这个引用所指向的对象的实例的内容(即id属性)做出了修改,在change()方法结束后,change()方法中的参数test依然被释放,但是在该方法的作用范围内,修改了Person对象实例的内容。在main方法中依然保持着这个引用即test,此时打印结果当然就是被修改过的Person对象实例的Id的值456。

在第3题中,将test赋给newTest,此时两个引用指向的是同一个对象的实例。故打印结果为456就没什么奇怪的了