结论:在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数,方法并不能修改传递给它的任何参数变量的内容。所以Java是按值传递
如果不能理解,看下面的分析:
基本数据类型
public class Test1 {
public static void main(String[] args) {
int n = 3;
System.out.println("Before change, n = " + n);
changeData(n);
System.out.println("After changeData(n), n = " + n);
}
public static void changeData(int nc) {
nc = 10;
}
}
运行结果:Before change, n = 3
After changeData(n), n = 3
很明显,n的值并没有被方法改变
分析:
- 方法调用时将n的值copy一份为nc
- 方法执行,将nc值赋值为10,原有n值不变
- 方法结束后,参数变量nc不再使用,被回收
当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数
引用(对象)数据类型
public class Test2 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello ");
System.out.println("Before change, sb = " + sb);
changeData(sb);
System.out.println("After changeData(n), sb = " + sb);
}
public static void changeData(StringBuilder stb) {
//stb = new StringBuilder();
stb.append("World!");
}
}
运行结果:
Before change, sb = Hello
After changeData(n), sb = Hello World!
sb 的值被改变了,也就是说方法参数类型如果是引用类型的话,引用类型对应的值将会被修改,这与我们上面的结论冲突,但是放开注释代码,会发现sb的值不变,符合预期结果
分析:
- 方法调用时将sb的值copy一份为stb
- sb和stb都保存StringBuilder的地址
- 未放开注释,调用apend方法可以修改该对象的内容
- 放开注释,stb指向新的new的对象,执行方法是对这个新对象内容进行操作,原有sb指向的对象内容不变
最后再看一个案例:
public class CallByValue {
private static User user=null;
private static User stu=null;
/**
* 交换两个对象
* @param x
* @param y
*/
public static void swap(User x,User y){
User temp =x;
x=y;
y=temp;
}
public static void main(String[] args) {
user = new User("user",26);
stu = new User("stu",18);
System.out.println("调用前user的值:"+user.toString());
System.out.println("调用前stu的值:"+stu.toString());
swap(user,stu);
System.out.println("调用后user的值:"+user.toString());
System.out.println("调用后stu的值:"+stu.toString());
}
}
class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return ("User: ["+"name = "+this.name+' '+"age = "+this.age+"]");
}
}
运行结果:
调用前user的值:User: [name = user age = 26]
调用前stu的值:User: [name = stu age = 18]
调用后user的值:User: [name = user age = 26]
调用后stu的值:User: [name = stu age = 18]
发现两个对象数据并没有交换,完全符合预期结果
理解下图分析流程