JAVA 中方法参数分为两大类:基本数据类型,引用对象。
方法在传递参数时都是采用值传递,不过对于基本数据类型传递的是数据的字面值,如(int a = 2;)此处传递的值为2;对于对象引用,传递则是引用地址指向。具体示例见如下代码:
public class Mill {
double num = 55.5D;
String str = new String("good");
char[] ch = {'a','b','c'};
boolean flag = true;
float f = 35.5f;
public static void main(String[] args) {
Mill ex = new Mill();
change(ex.str, ex.ch, ex, ex.f);
System.out.println(ex.string);
System.out.println(ex.ch);
System.out.println(ex.num);
System.out.println(ex.flag);
System.out.println(ex.f);
}
public static void change(String str,char[] ch,Mill mill,float f ) {
mill.num = 10.1D;
str = "test ok";
ch[0] = 'g';
mill = new Mill();
f = 44.5f;
mill.flag = false;
}
}
【输出结果】:
good
gbc
10.1
true
35.5
结合以上案例进行实际分析:
上面
change(String str,char[] ch,Mill mill,float f )
方法中String类型比较特殊,放在最后说。
char[] 字符数组和Mill为引用对象,float为基本类型。
mill.num = 10.1D;
通过上图,可以看出ex对象在进入change方法时,将自己的引用地址传递给了mill变量,所以此时两者指向的是同一个对象,所以在mill.num = 10.1D处改变了引用对象的成员属性num,所以在输出时候,ex.num的值也改变了。char[]数组ch虽然是mill的一个成员属性,但它也是引用地址传递,所以也是如此,不再解释。
f = 44.5f;
由于ex.f是float类型的,在经过方法时,传递的是它的字面值,此时,在栈内存中开辟了一块新的区域用来存放float变量f,所以在方法中操作f对ex.f的值没有任何影响,而在方法结束时,f的作用域结束,在随后一段时间内,会被jvm的垃圾回收器回收。
mill = new Mill();
mill.flag = false;
当mill进入change方法时,和ex指向的是同一个对象实例1,运行mill = new Mill();后,产生一个新的对象实例2,mill 此时指向实例2,然后mill.flag = false;改变的是实例2的属性,与实例1无关。
str = "test ok";
String虽然也是引用类型,但它比较特殊,这还涉及到String的字符串池,此处进行简单解释:
String类在内存中单独管理一个字符串池,它的创建机制是这样的:当创建一个新的字符串的时候,它会先从字符串池中查找是否有这个字符串,如果存在就讲声明变量指向这个字符串所在的地址,没有才去新建一个字符串维护在变量池中,字符串池中的字符串不会被修改。
开始时候,str 指向“good”字符串,进入change方法后,拷贝一个新的引用地址给change中str变量,然后运行str = “test ok”,他会发现没有这个字符串,然后就去新建了一个字符串“test ok”,此时,change中str变量指向“test ok”(此处改变了引用地址,而不是改变原有地址对应的内容),原有的地址依然是字符串“good”,所以在main中的ex.str指向的地址处内容并没有改变,还是“good”。