Day30--值传递和引用传递
Day30--值传递和引用传递
在 Java 中,参数传递采用的只有值传递,没有引用传递
值传递意味着是将实际参数的值复制一份传递给形式参数(也就是方法定义中接收参数的那些变量)。
值传递
示例:
创建一个叫change的静态方法,方法形式参数是int a,方法体是:a=10;
package com.liu.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
}
//返回值为空
public static void change(int a){
a=10;
}
}
当不调用change方法的时候,定义a=1,输出a的结果为1
package com.liu.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a=1;
System.out.println(a);//1
}
//返回值为空
public static void change(int a){
a=10;
}
}
当调用a的结果的时候,a的值还是1
package com.liu.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a=1;
System.out.println(a);//1
//调用change方法:
change(a);
System.out.println(a);//1
}
//返回值为空
public static void change(int a){
a=10;
}
}
为什么呢?
是因为返回值为void空吗?
那就修改一下返回值
package com.liu.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a=1;
change(a);
System.out.println(a);//1
}
//返回值为空
public static int change(int a){
a=10;
return 10;
}
}
结果仍然为1
可见,并不是简单的“返回值的问题”
事实上,在 Java 中,参数传递是值传递机制起主要作用,这与方法的返回值类型无关。
当把main方法中的变量a传递给change方法时,传递的是a的值(这里是1)的副本,此时change方法内部的a就相当于一个新的局部变量,它初始值是接收到的1。
即使change方法有返回值(比如改成返回int类型并返回修改后的a的值),在没有通过合适的方式在main方法中接收并处理这个返回值的情况下,change方法内部对其局部变量a的操作依然不会影响到main方法中的原始变量a。
在进一步理解:
- 值传递的基本概念(结合示例)
- 在 Java 中,参数传递是值传递。对于基本数据类型,比如
int,当你在main方法中定义int a = 1,此时a在内存中有一个存储位置,存储的值是1。 - 当调用
change(a)时,会把a的值(也就是1)复制一份传递给change方法中的参数a。这就好像是做了一个克隆操作,现在change方法中的a和main方法中的a是两个独立的个体,只是初始值相同。如果不想办法,把change方法中的a赋值给main方法中的a,则change方法中的a与main方法中的a无关 - 就好比你有一张写着数字
1的纸条(代表main方法中的a),当你把这个数字抄在另一张纸条上(代表传递给change方法的a),然后你在第二张纸条上修改数字为10,第一张纸条上的数字依然是1。
- 在 Java 中,参数传递是值传递。对于基本数据类型,比如
- 内存中的体现(简单理解)
- 在内存中,
main方法中的变量a存储在栈内存的一个位置。当调用change方法时,会在栈内存为change方法的参数a开辟一个新的空间,并且把main方法中a的值复制到这个新空间中。 - 所以当
change方法内部修改它自己的a变量时,是在修改这个新空间中的值,而不是修改main方法中a变量所在的空间的值。
- 在内存中,
准确的代码:
package com.liu.oop.demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a = 1;
// 调用修改后的change方法并接收返回值
a = change(a); //把**`change`方法中的`a`赋值给`main`方法中的`a`**
System.out.println(a);
}
// 修改为有返回值的方法
public static int change(int a) {
a = 10;
return a;
}
}
引用传递:
定义:
当进行引用传递时,传递给函数(或方法)的是变量的引用(可以理解为变量在内存中的地址),而不是变量的值的副本。这意味着函数内部对参数的操作会直接影响到原始变量。
示例:
package com.liu.oop.demo01;
//引用传递 :对象 本质上还是值传递
//对象:内存
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
Demo05.change(person);
System.out.println(person.name);//爱锟
}
public static void change(Person person){
//“person是一个对象:指向的--->Person person=new Person();这是一个具体的人,可以改变属性!”
person.name="爱锟";
}
}
//定义了一个person类,有一个属性 :name
class Person{
//String的默认值为null
String name;
}
详细解释:
以你代码中的 Person 对象为例,当在 main 方法中创建了 Person person = new Person(); 这个对象后,这个对象在内存中是有一个具体的存储位置的,我们可以把这个存储位置想象成一个地址(就像你家的门牌号一样,通过它能找到你家这个具体的地方)。
当执行 Demo05.change(person);,也就是把 person 对象传递给 change 方法时,并不是把整个 person 对象(包含它里面所有的属性值等内容)完整地搬到 change 方法里面去。而是把 person 对象在内存中的地址值(也就是那个 “门牌号”)复制了一份,传递给了 change 方法中的 Person person 这个形式参数。
这时候,在 change 方法里面的 person 参数和在 main 方法里面的 person 对象,它们在内存中的实际位置是不一样的(因为一个是原始的对象,一个是复制了地址值后的形式参数)。但是,它们都指向了内存中同一个实际的 Person 对象实体(就好比你和你的朋友都知道你家的门牌号,虽然你们两个人是不同的个体,但通过这个门牌号都能找到你家这个同一个地方)。
所以,当在 change 方法中通过 person.name = "爱锟"; 修改 person 参数的 name 属性时,实际上是通过这个复制过来的地址值找到了内存中那个真正的 Person 对象,并修改了它的属性值。而当回到 main 方法再次访问 person 对象的 name 属性时,就会发现它已经被修改了,因为它们指向的是同一个实际的 Person 对象。
这就是为什么说对象作为参数传递时,虽然表面上看起来像是引用传递(好像是直接把对象本身传递过去了,可以直接修改对象的属性),但本质上还是值传递(只是传递的是对象在内存中的地址值)的原因。
要注意的是,当进行引用传递时,传递给函数(或方法)的是变量的引用(可以理解为变量在内存中的地址),而不是变量的值的副本。这意味着函数内部对参数的操作会直接影响到原始变量。

浙公网安备 33010602011771号