Java的按值传递

来源:互联网 发布:sqlserver 回滚数据 编辑:程序博客网 时间:2024/06/16 22:19

近在看Java传值的问题,觉得醍醐灌顶啊!以前一直认为“对于基本变量类型,Java是按值传递,对于引用类型是按引用传递”,昨天看了些文章,发现自己真是too young too simple!Java中只有按值传递!!!

来详细解释一下原因。先看基本变量类型的例子:

//定义了一个改变参数值的函数  public static void changeValue(int x) {  x = x *2;  }  ... ...  //调用该函数  int num = 5;  System.out.println(num);  changeValue(num);  System.out.println(num);  

果还是5,大家都知道对不对。内存机制是这样的:
这里写图片描述
所以这里是把num存储的5这个值,传递到函数中去,因此函数中的变量值和原来的num是无关的。注意:值传递的精髓是:传递的是存储单元中的内容,而非地址或者引用!

再看看对象类型的例子:

class person {  public static String name = "Jack";  }  //定义一个改变对象属性的方法  public static void changeName(Person p) {  p.name = "Rose";  }  public static void main(String[] args) {  //定义一个Person对象,person是这个对象的引用  Person person = new Person();  //先显示这个对象的name属性  System.out.println(person.name);  //调用changeName(Person p)方法  changeName(person);  //再显示这个对象的name属性,看是否发生了变化  System.out.println(person.name);  }  

一次输出Jack,第二次输出Rose。好了,你要说“对啊,这就是按引用传递嘛!”注意,在java中,新创建的实体对象在堆内存中开辟空间,而引用变量在栈内存中开辟空间,也就是说,你new的对象是在堆中的,栈中存储的只是改对象在堆中的引用地址。看下面的图:
这里写图片描述
发现了吗,我们前面说的值传递的定义是传递存储单元中的内容,所以这个时候还是按值传递!
如果在changeName函数中重新new一个对象然后赋值给p呢?这个时候person本身还是不变的,他的过程是:在堆中重新创建一个对象,再把这个对象的引用地址放到p中,这个时候person和p存储的是不同对象的堆地址。

到这里,就想说说关于赋值操作,就是这个“=”。赋值操作其实是包含了两个意思:1、放弃了原有的值或引用;2、得到了 = 右侧变量的值或引用。对于基本数据类型变量,= 操作是完整地复制了变量的值。换句话说,“=之后,你我已无关联”。对于非基本数据类型变量,= 操作是复制了变量的引用。参数传递本质就是一种 = 操作。参数是变量,所有我们对变量的操作、变量能有的行为,参数都有。所以把C语言里参数是传值啊、传指针啊的那套理论全忘掉,参数传递就是 = 操作。
所以,像Java的List数据结构这些,在某个方法里面调用add函数这些,改变了原List,因为它操作的还是那个对象,并没有使用=,相当于放弃原引用。


以上 欢迎指正错误 共同学习

0 0
原创粉丝点击