Java中变量的传递,是传值,还是传引用?

  之前我对这个"经典"问题,认识很不深刻,直到我在项目中遇到类似下面的问题:

  示例A:

<SPAN style="FONT-SIZE: 18px">List<Person> perList = new ArrayList<Person>();

for (int i = 0; i < idList.length(); i++) {
 Person person = new Person();
 //设置属性
 person.setId(i+1);
 person.setName("Lin");
 person.setAge(10);
 //添加到List中
 perList.add(person);
}</SPAN>

  示例B:

<SPAN style="FONT-SIZE: 18px">List<Person> perList = new ArrayList<Person>();

Person person = new Person();
for (int i = 0; i < idList.length(); i++) {
 //设置属性
 person.setId(i+1);
 person.setName("Lin");
 person.setAge(10);
 //添加到List中
 perList.add(person);
}</SPAN>

  极为相似的两段代码,却有着极为不同的经历:

  示例A中person对象在for循环中创建,它的生命周期于for循环,一出for循环则销毁,因此new了idList。length()个person对象,并把每个person添加到perList中。因此,perList中是idList。length()个,id分别为1~n的person。(想象:点名,从1到n)

  而在示例B中,person对象在for循环外创建。示例B的结果是perList中为idList。length()个id为n的person。

  这是为什么呢?

  java中对象类型(Object)的变量传的是引用,第一次循环,person。setId(1),然后添加到perList中,第二次循环,还是同一个person对象,person。setId(2),相当于把person的id修改为2,然后添加到perList中。而之前放到perList中的person,存放的是指向person的一个引用,person对象已经被修改了,自然之前的"值"也更新了。因此,一套循环跑下来,perList中放了idList。length()个id为n的person对象。(也是同一个人叫了n次)

  思索:Java中变量是如何传递的?传值,还是传引用?什么时候传值,又是什么时候传引用呢?

  Java中,当向一个方法传递基本数据类型时,采用的是"传值"。即传递的只是该数据内容的一个副本。因此无论方法针对该副本值做怎样的改变,都不会影响到被传入的数据本身;传入对象数据类型时,采用的是"传引用"。即传入的是对象的一个引用,而不是对象本身(对象内容),方法的改变不会影响"引用关系",但却有可能改变被传入引用变量所引用的对象的内容。

  解析:

  JAVA中基本数据类型是在系统的栈中创建的,而对象型数据则是在堆中创建的。位于栈中的基本数据类型简化了调用机制,可以被直接调用而没有引用的概念,同时也抛弃了作为对象可以带来复杂属性设置的好处,属于轻装上阵,因而运行效率高;对象型数据正好相反,尽管运行效率低于前者,但可以向用户提供作为对象带来属性设置的好处,不过,用户必须也只能通过对象的引用变量来实现对对象内容的访问,不能象基本数据类型那样直接访问对象内容。

  总结:

  基本数据类型,传值,方法的改变不会影响传入的变量值;对象数据类型,传引用,方法的改变有可能会修改对象内容。我们如何结合对象的生命周期做到对对象变量的掌控自如。