总所周知,java虽然没有引用的概念,但是
java在传入参数时,实际传入的参数对象是外部对象的引用,也就是重新生成一个指向外部对象的对象,只不过这两个对象指向的是同一片内存对象而已 ,我们举例来说明参数和引用的关系,我们假定方法changeString为
public void changeString(String a ){
a = new String("I am b!" );
System.out.println(a);
}
那么当如下调用changeString(String a )方法时
String a = new String("I am a!" );
changeString(a);
......
java的做法实际等价于
String a = new String("abc" );
String b = a;
changeString(b);
............
也就是说在被调用方法内部,传入参数对象和外部对象是不同的对象;
虽然两者指向的是同一个内存对象,但是很容易将两者的联系断开 ,比如我们可以用如下的方法来测试一下
String a = new String("I am a!" );
System.out.println(a);
//调用changeString方法
changeString(a);
System.out.println(a);
结果应该为
I am a!;
I am b!;
I am a!;
也 就是说外部对象a的值并没有改变,这是因为在changeString(String a )方法内部,参数对象a并不是外部对象a了(其实你如果把方法改成public void changeString(String b)这样更能理解参数对象b和外部对象a是两个对象了),
参数对象a和外部对象a是两个对象,指向同一个内存对象new String("abc" ),但是在方法内部,当参数对象a被重新赋值时(a = new String("b" ))时,参数对象 a被重新指向一个新的内存对象new String("I am b!" ),这样参数对象a和外部对象a断开了关系 ,再没有任何联系了,因此外部对象a的值也不可能有什么变化。
如果某些时候你需要在方法内部改变原有对象的值怎么办,办法很简单,不要为参数对象指向新的内部对象,并在此基础上,调用参数对象的方法来改变内存对象,比如,我们考虑如下方法
public void changeBufferValue(StringBuffer sb){
sb.append("I am b!");
}
如下调用
StringBuffer a = new StringBuffer("I am a!");
System.out.println(a.toString());
changeBufferValue(a);
System.out.println(a.toString());
输入结果应该为
I am a!
I am a!I am b!
如果方法写成
public void changeBufferValue(StringBuffer sb){
sb = new StringBuffer("I am b!");
}
你应该知道结果是什么了吧!,因此当你期望方法内部能改变传入变量的值时,慎用"="号为参数对象重新赋值。
1、对于原始数据类型,也就是int、 long、char之类的类型,是传值的,如果你在方法中修改了值,方法调用结束后,那个变量的值没用改变。 2、对于对象类型,也就是Object的子类,如果你在方法中修改了它的成员的值,那个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把它指向一个其它的对象,方法调用结束后,原来对它的引用并没用指向新的对象。 代码如下:
public class Tester {
public static void main(String[] args) {
int primitive = 2;
changePrimitive(primitive);
//primitive的值依然是2
MyClass myClass = new MyClass();
changeObject(myClass);
//myClass仍然指向的是执行changeObject之前的那个对象
//但是myClass.i等于3了
}
public static void changePrimitive(int primitive) { primitive = 3; }
public static void changeObject(MyClass myClass) { myClass.i = 3; myClass = new MyClass(); } }