0基础java入门:第三十节.方法使用的补充 值传递与引用传递
这里的值传递和引用传递主要是因为参数的类型不同,引起的结果不同情况。
这里需要回忆一下Java中的数据类型。
基本类型:boolean、char、byte、short、int、long、float、double
引用类型:类、接口、数组
因此,变量类型也可分为两大类:基本类型和引用类型。
在分析值传递和引用传递之前,建议了解下以上变量类型在Java内存管理模型中的位置,如果对此有所了解,将更加有助于理解两种传递的方式^_^
在Java内存中,基本类型变量存储在Java栈(VM Stack)中,引用变量存储在堆(Heap)中,模型如下:
值传递和引用传递的定义:
这里要用实际参数和形式参数的概念来帮助理解
值传递:
方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。
引用传递:
也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
值传递演示
通过代码了解值传递的特性
代码演示:
package com.demo.test4;
public class Test1 {
public static void main(String[] args) {
// 定义一个变量 num
int num = 1;
System.out.println("方法调用前输出 "+num);
// 调用方法 test1 参数 num
test1(num);
System.out.println("方法调用后输出 "+num);
}
// 方法test1 参数 int a 是基本数据类型 ,这里是 值传递
public static void test1(int a){
System.out.println("方法中第1次输出 "+a);
// 给参数啊赋值为100
a=100;
System.out.println("方法中第2次输出 "+a);
}
}
运行结果:
分析一波:
代码中可以看出,test1方法的参数int a ,基本数据类型,所以这时 在方法内对形式参数的修改不会影响主函数中实际参数的值。内存中的变化如下
引用传递演示
通过代码了解引用传递特性
代码演示:
package com.demo.test4;
public class Test1 {
public static void main(String[] args) {
// 定义一个array int类型数组
int[] array = {1,2};
System.out.println("方法调用前输出 数组中第一个元素"+array[0]);
// 调用方法 test1 参数 array
test1(array);
System.out.println("方法调用后输出 数组中第一个元素 "+array[0]);
}
// 方法test1 参数 int[]数组 arr 是基本数据类型 ,这里是 值传递
public static void test1(int[] arr){
System.out.println("方法中第1次输出 形式参数数组第一个值 "+arr[0]);
// 给参数数组 中的 0下标第一个元素赋值赋值为100
arr[0]=100;
System.out.println("方法中第2次输出 形式参数数组第一个值"+arr[0]);
}
}
运行结果:
分析一波:
代码中 方法 test1参数为 int[ ] 数组,这时方法使用的是引用传递。通过结果可以看出 ,在方法体内修改形式参数时,实际参数的值也发生了改变。内存分析如下
总结
通过上面的分析,对于传递方式应该很好理解了
注意:这里要特殊考虑String,以及Integer、Double等基本类型包装类,它们的类前面都有final修饰,为不可变的类对象,每次操作(new或修改值)都是新生成一个对象,对形参的修改时,实参不受影响,与值传递的效果类似,但实际上仍是引用传递。
总结:
1)基本类型变量作为方法中的参数,进行的值传递,对形参的修改不影响实参的原来的值;
2)非final修饰的类、数组、接口作为方法中的参数,进行的引用传递(地址传递),对形参修改后实参也会改变,因为二者指向的是同一个实例;
3)final修饰的类作为方法中的参数,因为final的存在初始化后值不可变,每次操作都相当于产生一个新的实例对象,因此对形参修改时,实参也不受影响。
文章部分转载于 CSDN博主「a41664256」的原创文章。相互学习