Java 传参传值
案例代码
public class PassParamExplain {
public static void main(String[] args) {
//example A
System.out.println("example A:");
Integer a = 2018;
passInteger(a);
System.out.println(a);
a = passInteger(a);
System.out.println(a);
//example B
System.out.println("example B:");
Pojo pojo1 = new Pojo(2021, "2021");
passPojo(pojo1);
System.out.println("pojo1 x:" + pojo1.getX() + " y:" + pojo1.getY());
//example C
System.out.println("example C:");
Pojo pojo2 = new Pojo(2022, "2022");
pojo2 = passPojo(pojo2);
System.out.println("pojo2 x:" + pojo2.getX() + " y:" + pojo2.getY());
//example D
System.out.println("example D:");
Pojo pojo3 = new Pojo(2023, "2024");
passPojoAndReassign(pojo3);
System.out.println("a: pojo3 x:" + pojo3.getX() + " y:" + pojo3.getY());
pojo3 = passPojoAndReassign(pojo3);
System.out.println("b: pojo3 x:" + pojo3.getX() + " y:" + pojo3.getY());
}
public static Integer passInteger(Integer arg) {
arg = 2019;
return arg;
}
public static Pojo passPojo(Pojo pojoA) {
pojoA.setX(2019);
pojoA.setY("2019");
return pojoA;
}
public static Pojo passPojoAndReassign(Pojo pojoB) {
pojoB = new Pojo(2020, "2020");
return pojoB;
}
}
public class Pojo {
private Integer x;
private String y;
public Pojo(Integer x, String y) {
this.x = x;
this.y = y;
}
public Integer getX() {
return x;
}
public void setX(Integer x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
}
案例分析
-
example A
- 调用passInteger(a)时,产生了一个新的局部变量arg,并且变量arg被赋值为a存放的引用,紧接着执行方法passInteger内的赋值语句 arg = 2019,此时局部变量arg被重新赋值为一个新的引用;
- 只执行passInteger(a)并不会修改main方法变量a的值(即变量a存放的引用),因为passInteger方法只对局部变量arg重新赋值并返回,调用passInteger(a)方法时仅仅是把变量a存放的引用传给了变量arg
- 执行 a = passInteger(a)时; 因为passInteger方法返回了一个新的引用(且每次调用都返回一个新引用,因为 arg = 2019 语句产生了新的对象), 并且赋值给了变量a,因此main方法变量a当然是改变了
-
example B
- 调用passPojo(pojo1)时,产生了一个新的局部变量pojoA,并且变量pojoA被赋值为参数pojo1的值(即pojo1存放的引用),此时变量pojoA的值为变量pojo1存放的引用(该引用指向pojo1对象的内存空间),两个变量存放的引用是相同的;
- 执行pojoA.setX(2019); pojoA.setY("2019"); 修改了该引用指向的内存空间的数据,因此即使仅仅调用passPojo(pojo1),变量pojo1指向的内存空间的数据也会相应得到改变
-
example C
- pojo2 = passPojo(pojo2);与passPojo(pojo2);的区别是前者接收了方法passPojo返回的引用,并赋值给了变量pojo2;但根据example B的分析可得,调用passPojo(pojo2)返回的引用其实和调用之前pojo2存放的引用是指向同一个空间的引用,
- 只是变量pojoA存放的是变量pojo2指向的内存空间引用的副本而已;
-
example D
- example D和example A本质其实是相同的,
- passPojoAndReassign(pojo3)时,产生了一个新的局部变量pojoB,并且变量pojoB被赋值为pojo3存放的引用,紧接着执行方法内语句pojoB = new Pojo(2020, "2020"); 此时局部变量pojoB被重新赋值为一个新的引用,该新引用指向new Pojo(2020, "2020")对象存放的内存空间;只修改了变量pojoB存放的引用,变量pojo3没有任何修改;
- 只执行passPojoAndReassign(pojo3),由于变量pojo3没有接收passPojoAndReassign方法的返回值所以并不会修改main方法变量pojo3存放的引用,而且passPojoAndReassign方法内也没有修改变量pojo3存放的引用指向的内存空间的数据,因此变量pojo3没有任何改变;
- pojo3 = passPojoAndReassign(pojo3);与passPojoAndReassign(pojo3)的唯一的不同点是前者用变量pojo3接收了passPojoAndReassign方法返回的新的引用,且每次调用passPojoAndReassign方法都返回一个新引用,因此main方法中变量pojo3存放的引用被改变了
案例数据变化打印输出
example A:
2018
2019
example B:
pojo1 x:2019 y:2019
example C:
pojo2 x:2019 y:2019
example D:
a: pojo3 x:2023 y:2024
b: pojo3 x:2020 y:2020