今天无意中发现一个好玩的 java 基础问题,就是当 A 方法调用 B 方法时,如果改变了 B 中的实参, A 中的形参是否会发生改变?
实践是得出答案最好的方法,为了搭建测试环境,这里先写了一个实体以便后面进行测试,下面是实体
public class DemoBean {
private String str1;
private String str2;
private String str3;
private String str4;
public String getStr1() {
return str1;
}
public void setStr1(String str1) {
this.str1 = str1;
}
public String getStr2() {
return str2;
}
public void setStr2(String str2) {
this.str2 = str2;
}
public String getStr3() {
return str3;
}
public void setStr3(String str3) {
this.str3 = str3;
}
public String getStr4() {
return str4;
}
public void setStr4(String str4) {
this.str4 = str4;
}
@Override
public String toString() {
return "DemoBean{" +
"str1='" + str1 + '\'' +
", str2='" + str2 + '\'' +
", str3='" + str3 + '\'' +
", str4='" + str4 + '\'' +
'}';
}
}
接下来看一段简单的测试代码:
public class TestDemo {
public static void main(String[] args) {
new TestDemo().testBegin();
}
public void testBegin() {
DemoBean demoBean = new DemoBean();
demoBean.setStr1("str1");
String msg = "value";
ArrayList<String> list = new ArrayList<>();
int a = 0;
System.out.println("========>testReferenceType:");
testReferenceType(demoBean);
demoBean.setStr3("str3");
System.out.println(demoBean.toString());
System.out.println("========>testReferenceTypeNotBack:");
testReferenceTypeNotBack(demoBean);
demoBean.setStr4("str4");
System.out.println(demoBean.toString());
System.out.println("========>testBasicType:");
testStringType(msg);
System.out.println(msg);
System.out.println("========>testBasicTypeNotBack:");
testStringTypeNotBack(msg);
System.out.println(msg);
System.out.println("========>testBasicType:");
Object s = testStringType(msg);
System.out.println(s);
System.out.println("========>testArrayList:");
testArrayList(list);
System.out.println(list.get(0));
System.out.println("========>testBasicType:");
int i = testBasicType(a);
System.out.println(a);
System.out.println(i);
}
public DemoBean testReferenceType(DemoBean demoBean) {
demoBean.setStr2("str2");
return demoBean;
}
public void testReferenceTypeNotBack(DemoBean demoBean) {
demoBean.setStr2("str2");
}
public String testStringType(String msg) {
msg = "testBasicTypeValue";
return msg;
}
public void testStringTypeNotBack(String msg) {
msg = "testBasicTypeNotBackValue";
}
public List<String> testArrayList(List<String> list) {
list.add("testArrayListValue");
return list;
}
public int testBasicType(int a) {
a = 10;
return a;
}
}
对应的输出结果:
========>testReferenceType:
DemoBean{str1='str1', str2='str2', str3='str3', str4='null'}
========>testReferenceTypeNotBack:
DemoBean{str1='str1', str2='str2', str3='str3', str4='str4'}
========>testBasicType:
value
========>testBasicTypeNotBack:
value
========>testBasicType:
testBasicTypeValue
========>testArrayList:
testArrayListValue
========>testBasicType:
0
10
进程已结束,退出代码为 0
看到这里,我们会发现一个有趣的现象,在引用testReferenceType(demoBean) 方法时,我们并没有进行接收该方法返回的实参,而是在调用后直接打印调用钱实例化的引用对象实例,结果发现实参改变后形参也发生了改变。但是像t estBasicType 和 testStringType 两个方法就没有改变形参的值。
打印形参对象和实参对象的地址,结果如下:
========>testReferenceType:
org.today.DemoBean@7c30a502
org.today.DemoBean@7c30a502
结论:除了 String 这个特殊的引用类型外,其余所以的引用类型,当被作为参数传递时,实参发生改变则形参也会发生改变。原因是引用类型作为参数时,传递的是地址,所以,形参和实参是同一个地址,这也就是为什么引用类型作为参数传递时实参改变形参也改变的原因(因为地址相同,所以其实实参和形参就是同一个东西)。但是基本数据类型作为参数时传递的是值,形参和实参地址是不一样的(也就是说根本就是两个不同的实例),所以实参改变并不会影响到形参。