问题背景:
今天做题,遇到一个代码判断题,结果一直做错。
题目如下:
public class Point{
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public void setLocaton(int x,int y){
this.x = x;
this.y = y;
}
public static void main(String[] args){
Point p1 = new Point(0,0);
Point p2 = new Point(0,0);
modifyPoint(p1,p2);
System.out.println(p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
}
private static void modifyPoint(Point p1, Point p2){
Point tempPoint = p1;
p1 = p2;
p2 = tempPoint;
p1.setLocaton(5,5);
p2 = new Point(5,5);
}
}
最终输出结果是什么:
A. [0,0], [0,0]
B. [5,5], [0,0]
C. [0,0], [5,5]
D. [5,5], [5,5]
正确答案是
B
[
0
,
0
]
,
[
5
,
5
]
B [0,0],[5,5]
B[0,0],[5,5]
我百思不得其解,因为我认为modifyPoint(Point p1, Point p2)
里p1设置为[5,5], p2新建且初始化为[5,5]
,应该输出D选项。
在查询过程中,发现值传递和引用传递的说法:
- 值传递: 就是复制,把数据传过去, 形参, 函数内操作不改变原来的变量
- 引用传递:类似指针,传的地址, 要改变操作一起改变。
并且还有JAVA只有值传递的说法, 我一开始也没懂,直到把对象的内存地址打印出来才明白。
建议使用这个自己跑一下,体会下菜鸟JAVA在线编程环境
public class Point{
private int x;
private int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
public void setLocaton(int x,int y){
this.x = x;
this.y = y;
}
public static void main(String[] args){
Point p1 = new Point(0,0);
Point p2 = new Point(0,0);
System.out.println("p1 内存地址="+System.identityHashCode(p1));
System.out.println("p2 内存地址="+System.identityHashCode(p2));
System.out.println("1>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
modifyPoint(p1,p2);
System.out.println("函数后 p1 内存地址="+System.identityHashCode(p1));
System.out.println("函数后 p2 内存地址="+System.identityHashCode(p2));
System.out.println("7>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
System.out.println("------->"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
}
private static void modifyPoint(Point p1, Point p2){
System.out.println("函数内 p1 内存地址="+System.identityHashCode(p1));
System.out.println("函数内 p2 内存地址="+System.identityHashCode(p2));
Point tempPoint = p1;
System.out.println(
"函数内 temp 内存地址="+System.identityHashCode(tempPoint));
System.out.println("2>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
p1 = p2;
System.out.println(
"p1=p2操作, p1 内存地址="+System.identityHashCode(p1));
System.out.println("3>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
p2 = tempPoint;
System.out.println(
"p2=temp操作, p2 内存地址="+System.identityHashCode(p2));
System.out.println("4>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
p1.setLocaton(5,5);
System.out.println(
"p1.set操作, p1 内存地址="+System.identityHashCode(p1));
System.out.println("5>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
p2 = new Point(5,5);
System.out.println(
"p2 = new 操作, p2 内存地址="+System.identityHashCode(p2));
System.out.println("6>>>"+p1.x+" "+p1.y+";;"+p2.x+" "+p2.y);
}
}
输出结果为:
p1 内存地址=225534817
p2 内存地址=640070680
1>>>0 0;;0 0
函数内 p1 内存地址=225534817
函数内 p2 内存地址=640070680
函数内 temp 内存地址=225534817
2>>>0 0;;0 0
p1=p2操作, p1 内存地址=640070680
3>>>0 0;;0 0
p2=temp操作, p2 内存地址=225534817
4>>>0 0;;0 0
p1.set操作, p1 内存地址=640070680
5>>>5 5;;0 0
p2 = new 操作, p2 内存地址=1421795058
6>>>5 5;;5 5
函数后 p1 内存地址=225534817
函数后 p2 内存地址=640070680
7>>>0 0;;5 5
------->0 0;;5 5
关键看着几步:
2>>>0 0;;0 0
p1=p2操作, p1 内存地址=640070680 !!这里p1指向了原来p2指向的内存地址
3>>>0 0;;0 0
p2=temp操作, p2 内存地址=225534817 !!p2指向了temp指向的内存地址
4>>>0 0;;0 0
p1.set操作, p1 内存地址=640070680
5>>>5 5;;0 0
p2 = new 操作, p2 内存地址=1421795058 !!新内存地址
6>>>5 5;;5 5
然而由于值传递,函数外的对象指针,内存地址并没有变:
函数后 p1 内存地址=225534817
函数后 p2 内存地址=640070680
7>>>0 0;;5 5
所以输出结果的时候,正好是【0,0】,【5,5】
![在这里插入图片描述](https://img-blog.csdnimg.cn/b150ab59227149aa8c52f8a6af086a0b.png#pic_center)
总结:
JAVA 函数 对象,传的是地址, 交换的也是地址,做好这个对应就行。(我居然蠢到打印了内存地址,才反应过来)