以前对这种东西就是硬记下来,但是自己完全没有真正理解,今天写代码的时候突发奇想测试了一下,恍然大悟。
就三句话:
第一:java方法基本数据类型是传值,对象类型传引用,这是千真万确的。
第二:当参数是对象时,无论方法体内进行了何种操作,都不会改变实参对象的引用。
第三:当参数是对象时,只有在方法内部改变了对象的内容时,才会改变实参对象内容。
关于第一点,不赘述了。
先说第三点:
public class TestChange {
public int age;
public Object ob;
}
public class TestEqual {
/**
* @param args
*/
public static void main(String[] args) {
TestChange tc = new TestChange();
tc.age = 10;
tc.ob = new Object();
TestEqual te = new TestEqual();
System.out.println(tc.ob.hashCode());
te.change(tc);
System.out.println(tc.ob.hashCode());
}
void change(TestChange tc) {
//tc = new TestChange();
tc.ob = new Object();
System.out.println(tc.ob.hashCode());
}
}
打印出来的hashcode(在object里就是对象地址)如下:
1353056826
1121736499
1121736499
说明了传对象的引用进去,如果改变的是对象内部的变量,即使这个变量是一个对象,此对象也会被改变;因为此变量的地址是在原对象地址内的,相当于改变传入对象里的内容,而不是改变引用本身。
最后是第二点:
public class TestEqual {
/**
* @param args
*/
public static void main(String[] args) {
TestChange tc = new TestChange();
tc.age = 10;
TestEqual te = new TestEqual();
System.out.println(tc.age);
te.change(tc);
System.out.println(tc.age);
}
void change(TestChange tc) {
tc = new TestChange();
tc.age = 5;
System.out.println(tc.age);
}
}
打印出来的是:
10
5
10
在对传入的引用进行重新赋值后,函数外的引用关联的对象没变。
原因是这样的,首先要理解一点,引用也是一种类型,可以类比为C语言里的指针,Thinking in Java里说过引用也是和基本类型一样,存放在栈里的,值就是所指向对象的地址。
好,那么函数参数里传递对象,实际上是引用拷贝,记住——并不是原来的引用,只不过是一个临时拷贝的引用变量,此引用变量和原引用指向了同一块地址而已。
当在函数内对引用进行重定义时,实际上是把拷贝的引用指向了另一块内存,等于这样就和原引用没关系了,理解到这里就明白了。