分类: Java
2012-10-24 20:21:18
Java中变量的传递, 是传值, 还是传引用?
之前我对这个"经典"问题, 认识很不深刻. 直到我在项目中遇到类似下面的问题:
示例A:
示例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中基本数据类型是在系统的栈中创建的, 而对象型数据则是在堆中创建的. 位于栈中的基本数据类型简化了调用机制, 可以被直接调用而没有引用的概念, 同时也抛弃了作为对象可以带来复杂属性设置的好处, 属于轻装上阵, 因而运行效率高; 对象型数据正好相反, 尽管运行效率低于前者, 但可以向用户提供作为对象带来属性设置的好处, 不过, 用户必须也只能通过对象的引用变量来实现对对象内容的访问, 不能象基本数据类型那样直接访问对象内容.
总结:
基本数据类型, 传值, 方法的改变不会影响传入的变量值; 对象数据类型,传引用, 方法的改变有可能会修改对象内容. 我们如何结合对象的生命周期做到对对象变量的掌控自如.