Java中的值传递和引用传递

调用方法时,我需要传递实参给方法,在方法内部会改变这些实参的值。
在Java语言中,方法执行完毕后,这些实参的值会有变化吗。

先简单介绍一下什么是值传递,什么是引用传递

  • 值传递:
    > 调用方法时,传入的是实参的一个拷贝,原先的数据在方法结束后没有被改变

  • 引用传递:
    > 调用方法时,传入的是实参的地址,而不是拷贝,原先的数据会根据方法内容变化
    > 注意:基本数据类型也是有地址的

Java是哪一种传递模式呢?

严格来说,Java只存在值传递,方法得到的是实参的拷贝,而不是变量的地址。

我们先搞清楚一些相关概念:

  • 基本数据类型:都存储在栈上,不存在引用,直接保存数据值
  • 引用数据类型:在jvm栈上保存堆上对象的地址,在堆内存上开辟一片空间,用于存放实体,即引用数据类型的具体信息

对于基本数据类型而言,方法调用过程如下:

  * 在调用的方法的栈帧中初始化一个实参的副本;
  * 对这个副本进行操作,原先main方法栈帧的变量的值不会发生变化;
  * 并且这个方法执行完毕后,随着方法出栈,这个实参的副本也被销毁了

对于引用数据类型而言,方法调用过程如下:

  * 在调用的方法的栈帧中声明一个引用的拷贝,因为是拷贝,所以这个引用中存的内存地址和原先的引用一样
  * 结果就是,这个副本仍然指向了原先引用所指向的对象
  * 对这个引用的副本进行操作,原先main方法栈帧的引用不会发生变化,但由于指向的是同一对象
  * 结果就是,引用和引用拷贝指向的对象本身被改变了
  * 方法结束后,这个引用拷贝也被销毁了

举例分析

下面是一个数组交换的demo,我们根据这个demo来分析一下,在传参过程中变量是怎么变化的:

    
    public static void main(String[] args) {
        int[] a = {20, 21, 22};
        int[] b = {23, 24, 25};
        System.out.println("============原始数组a/b==============");
        System.out.print("数组a: ");
        printArray(a);
        System.out.print("数组b: ");
        printArray(b);
        System.out.println("==========swapArray方法中的数组==============");
        swapArray(a, b);
        System.out.println("==========swapArray后的数组a/b==============");
        System.out.print("数组a: ");
        printArray(a);
        System.out.print("数组b: ");
        printArray(b);

    }

    public static void swapArray(int[] arr1, int[] arr2) {
        int[] tmp = arr1;
        arr1 = arr2;
        arr2 = tmp;
        System.out.print("数组arr1: ");
        printArray(arr1);
        System.out.print("数组arr2: ");
        printArray(arr2);
    }

    public static void printArray(int[] arr){
        for (int i = 0; i < arr.length-1; i++) {
            System.out.print(arr[i]+" , ");
        }
        System.out.println(arr[arr.length-1]);
    }

程序输出


============原始数组a/b==============
数组a: 20 , 21 , 22
数组b: 23 , 24 , 25
==========swapArray方法中的数组==============
数组arr1: 23 , 24 , 25
数组arr2: 20 , 21 , 22
==========swapArray后的数组a/b==============
数组a: 20 , 21 , 22
数组b: 23 , 24 , 25

显然,main中的原始数组 a 和数组 b 经过swapArray方法后,值并没有改变
同时,方法中的数组确实交换成功了,可以看出来Java

程序运行过程内存分析

swapArray方法入栈

main方法先入栈在栈底,在堆上开辟两块连续的内存空间给引用数据类型变量 a 和 b,

swapArray方法再入栈,传入实参a,b,完成两个数组arr1 arr2 的交换

swapArray方法出栈

swapArray方法出栈,一旦出栈方法内的局部引用数据类型变量也销毁了,图中可以看出,main方法中的原数组仍然没有变化,说明再方法传参中,变量使用的是值传递,并没有改变原始数据

  • refering:
    • JavaGuide: 为什么Java中只有值传递?
    • 王道训练营课件
posted @ 2021-01-28 22:25  海绵698  阅读(359)  评论(0)    收藏  举报