面试专题:值传递和引用传递的问题

2023-12-26 14:57:34 浏览数 (1)

前言

在Java编程中,参数传递有两种方式:值传递和引用传递。这两种传递方式决定了变量在方法内部的变化如何影响原始变量。本文将深入探讨这两种传递方式的概念、应用和注意事项,并且从面试题入手,分栈堆内存的情况。

一、值传递与引用传递

值传递是指在方法调用时将实际参数(原始变量)的副本传递给形式参数。这意味着在方法内部对形式参数的修改不会影响实际参数。值传递在传递基本数据类型(如int、float、double等)和引用数据类型的包装类(如Integer、Float、Double等)时发生。

引用传递是指在方法调用时将实际参数的引用(内存地址)传递给形式参数。这意味着在方法内部对形式参数的修改可能会影响实际参数。引用传递通常发生在对象类型上。

二、面试案例

看一下面试题,看起来就几行代码很简单,那么到时a和b最终结果是什么呢?

运行结果,输出的是AB B,而不是AB,AB

占堆内存分析:

一开始栈中有a和b变量,分别指向堆中的A和B。a->000x1(A),b->000x2 (B)

operator(a, b);操作,新增了方法局部变量x和y,并且也是指向A和B。x->000x1(A),y->000x2 (B)

接下来,x操作append,拼接y,x指向对应的内存值000x1(A)变成了000x1(AB);而y = x,表示的是y指向了x的内存地址。

最终y->x->000x1(AB)。此时,a和b的只想其实都没变化,a还是指向000x1,b还是指向000x2。所以a和b对应的值是

AB和B。

如图最终栈堆内存图:

如果改成这样,就可以看到四个变量最终的值了,跟我们上面分析的结果一样。

代码语言:java复制
public class Test {
    public static void main(String[] args) {
        StringBuffer a = new StringBuffer("A");
        StringBuffer b = new StringBuffer("B");
        operator(a, b);
        System.out.println(a   " "   b);
    }

    public static void operator(StringBuffer x, StringBuffer y) {
        x.append(y);
        y = x;
        System.out.println("y:"   y   " ,x:" x);
    }
}

最终结果

总结

这个问题其实涉及到了,变量的范围,x和y只有在operator生效,不会影响到a和b,但是如果operator接受的是对象,则传递的是地址而不是值,如果方法改变地址的内容(比如x.append(y)),外部引用的变量(比如a)获取到的值也会更新。所以方法的参数传递机制,如下规则: (1)形参(形参是在函数定义中声明的参数)是基本数据类型 传递数据值 (2)实参(实参是在函数调用时传递给函数的值)是引用数据类型 传递地址值 特殊的类型:String、数组 包装类等对象不可变性

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

0 人点赞