针对如上问题,先说结论,java 调用方法时,参数传递的是值。也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
有很多初学者看到一些资料中提到“方法传递对象时,传递的是对象的引用(pass-by-reference)”,这让他们又很混乱,其实对象传递的是复制引用对象的值,也可以理解为存放引用原始对象引用的指针值,如果你觉得比较难理解,看下面的图解。
方法传递对象类型
public class NationDemo {
public static void main(String[] args) {
Nation usa = new Nation("usa");
Nation america = usa;
// we pass the object to foo
foo(usa);
// usa variable is still pointing to the "usa" when foo(...) returns
System.out.println(usa.getName().equals("usa")); // true
System.out.println(usa.getName().equals("china")); // false
System.out.println(usa == america); // true
}
public static void foo(Nation nation) {
System.out.println(nation.getName().equals("usa")); // true
// change nation inside of foo() to point to a new Nation instance "china"
nation = new Nation("china");
System.out.println(nation.getName().equals("china")); // true
}
static class Nation {
private String name;
public Nation(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
上图直观解释了方法传递对象时,传递的是存放对象地址的值,传递的参数 nation
为复制 usa
变量存放的指向 Nation(0x1234)
的对象,后在方法中存放的地址变为另一个对象 Nation(0x5678)
,方法调用结束后,usa
变量引用的对象内容没有任何变动。从图上也可以看出,变量参数都是存放在栈(stack)空间(属于私有线程栈),类实例即对象是存放在堆(heap)空间上的(共享空间)。
方法传递基本类型
public class CallByPrimitiveTypeValueDemo {
public static void main(String[] args) {
boolean bool = true;
char c = 'a';
byte b = 1;
short s = 11;
int i = 101;
long l = 1001L;
float f = 10001f;
double d = 100001d;
bar(bool, c, b, s, i, l, f, d);
System.out.println(bool);
System.out.println(c);
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
}
public static void bar(boolean bool, char c, byte b, short s, int i, long l, float f, double d) {
bool = false;
c = 'b';
b = 2;
s = 12;
i = 102;
l = 1002L;
f = 10002f;
d = 100002d;
}
}
方法传递基本类型比对象参数更好理解,方法中传递的是基本类型的值,且都发生在栈空间内。