最近在看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,因为它操作的还是那个对象,并没有使用=,相当于放弃原引用。
以上 欢迎指正错误 共同学习