前言:
在我们的Java中,基本类型的变量和对象的引用变量是存在栈中的,而堆中存储的是由new指令等所创建的对象和数组。
实际上,引用变量就是一个指针,它指向堆内存中的对象实例。
值传递与引用传递的区别:
值传递(pass by value):
值传递的意思就是在调用函数时将参数复制一份(称为形参),那么这样我们在函数中修改形参就不会影响到实参(实参不会发生改变)。
引用传递(pass by value):
引用传递的意思就是在调用函数时传入参数的地址,那么函数中通过地址就可以改变该地址(引用)所指向的实例对象,从而影响到实际参数。
Java中的值传递:
那么在Java中是用的值传递还是引用传递呢?
答案是 值传递 !!!
那么为什么说在Java中使用的是值传递呢?让我细细道来~~
在Java中如果我们要new一个对象,我们通常都会这样写:
class Balloon {
}
public class Main {
public static void main(String[] args) {
Balloon rope = new Balloon();//Balloon(气球), rope(绳子)
}
}
以上的Balloon rope = new Balloon();这个语句可以分成两部:
Balloon rope;//先定义一个引用变量
rope = new Balloon();//再将这个引用变量指向新建的实例对象
我们可以想象出我们的引用变量rope是一根绳子,new出来的对象是一颗气球:
![](https://i-blog.csdnimg.cn/blog_migrate/85451b32f1002c258545ef8109b75431.png)
搞清楚了这个概念,那我们来试着分析一下下面的代码吧~~
解析1:
public class Main {
public static void MyChange(int a) {
a = 100;
System.out.println("在MyChange函数中:a = " + a);
}
public static void main(String[] args) {
int a = 0;
System.out.println("在执行MyChange函数前:a = " + a);
MyChange(a);
System.out.println("在执行MyChange函数后:a = " + a);
}
}
执行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/ae197f967ff1045c2993a2f33d271b54.png)
这一段代码应该不难理解,由于我们的Java的变量是值传递的,在函数MyChange里的int a其实是实参的一份拷贝,那么在函数MyChange中修改(形参)a自然不会影响到在主函数main里的(实参)a了。
解析2:
第二段代码:
class Balloon {
public String name;
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void MyChangeBalloon(Balloon rope1) {
rope1.setName("灰太狼");
System.out.println("在MyChange函数中:rope1 = " + rope1.name);
}
public static void main(String[] args) {
Balloon rope = new Balloon();
rope.setName("喜羊羊");
System.out.println("在执行MyChangeBalloon函数前:rope = " + rope.name);
MyChangeBalloon(rope);
System.out.println("在执行MyChangeBalloon函数后:rope = " + rope.name);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/c313002a53ed67a1decceedd06609bdb.png)
在这里发现rope的name发生了改变。这时候就会有小伙伴会问了,不是说Java的变量是值传递的吗?为什么这里的实参会发生改变呢???
我给大家画一个图大家应该就能懂了:
![](https://i-blog.csdnimg.cn/blog_migrate/020a84db6d5c8f318d5fc09f856a93ce.png)
也就是说rope1所指向的对象和rope所指向的对象是同一个,那么修改rope1所指向的对象也就是修改rope所指向的对象~~
这里值传递里的“值”指的是引用变量(也就是rope这根绳子,它被复制了一份rope1)。
解析3:
再来一个实例来帮助大家理解:
我们就加了一条new语句!!!看看效果~~
class Balloon {
public String name;
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void MyChangeBalloon(Balloon rope1) {
rope1 = new Balloon();//我们就加了一条new语句!!!看看效果~~
rope1.setName("灰太狼");
System.out.println("在MyChange函数中:rope1 = " + rope1.name);
}
public static void main(String[] args) {
Balloon rope = new Balloon();
rope.setName("喜羊羊");
System.out.println("在执行MyChangeBalloon函数前:rope = " + rope.name);
MyChangeBalloon(rope);
System.out.println("在执行MyChangeBalloon函数后:rope = " + rope.name);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/d131473700f085dd5373267bce497969.png)
发现结果并没有发生改变~~ 我再画一张图~~
![](https://i-blog.csdnimg.cn/blog_migrate/fb97b407a7fd7c9f07c04d4582a9b92c.png)
也就是说rope1所指向的对象和rope所指向的对象不是同一个,那么修改rope1所指向的对象与rope所指向的对象无关~~
小总结:
其实严格来讲Java是传参是共享传递(call by sharing),共享传递是值传递的一种~~
共享传递就是在给函数传递参数的时候传递该参数的引用变量(如果是基本类型,则直接复制其值),并且将该引用变量复制一份,那么在函数内部进行操作的时候就会通过这个引用变量寻值来操作了~~
所以,你可以说Java是值传递,亦可以说是共享传递。
那么在函数中,我们要注意引用变量的指向,以及它有没有指向新的对象,这对我们程序的最终结果有着巨大的影响~~
最后贴两道题目给大家试一试吧
1.
![](https://i-blog.csdnimg.cn/blog_migrate/a808df0c8c7b84dee9e0c9af280ce626.png)
2.
![](https://i-blog.csdnimg.cn/blog_migrate/b890128663557f9423dbd3be87cd560a.png)
答案:
1.
![](https://i-blog.csdnimg.cn/blog_migrate/74c0578d1a1af3c682049fa7153d9f58.png)
2.
![](https://i-blog.csdnimg.cn/blog_migrate/6aee72f301bc118ec5063e04640305c4.png)
最后希望大家能够坚持学习,不断超越自己~~