Java 方法传参,到底是值传递,还是引用转递?

最近写代码时遇到了一个 “bug”,首先先让来看看是怎么样的;

    public void merge(int A[], int m, int B[], int n){
        Arrays.copyOf(A, m + n);
        System.arraycopy(B,0, A, m, n);
    }

我写了这么一个函数将 B合并到A中

        int[] A = {23,34,2,3};
        int[] B = {2,4,1,5,3};
        merge(A,4,B,4);
        log.info(Arrays.toString(A));

大家觉得上述代码可以运行成功么?

consle: [23, 34, 2, 3]

答案是不行,有人会说了,是你函数写错了、是你电脑的问题。但其实都不是,问题在于 Arrays.copyOf 是深拷贝,它返回的是一个新的数组。

此时 merge 方法中 的 A又重走了一遍 赋值操作引用指向了新的 数组;

因此 此时 主函数 中的 A 没有任何改变

JAVA 方法传递参数


要探讨这个问题,首先我们要靠清楚一个概念,常见参数类型;

常见参数类型大致分为两种:基本类型引用类型

1. 基本类型:

boolean, char, short, int, long, float, double, byte
这些类型声明的对象,当未使用 static 关键字时, 都是存储在 虚拟机栈栈帧中的。

当方法A 调用 方法B 对应的就是 入栈
在这里插入图片描述

当方法B 执行完毕返回 对应的就是 出栈
在这里插入图片描述

从图中我们可以看出,A()和 B()“独立” 或者说 “局部”

的确如此,除了B()进栈时传递的参数, 和B()出栈时的返回值(return)。他们的确没有过多交互;

2. 引用类型:
	A a = new A();
	B b = a;

此时 a 指向的是 堆中 被实例化的对象 aObject, 现在的 a 其实是一个引用。

而当 b = a时,此时的 b 也指向的也是 堆中 被实例化的对象 aObject

当此时 你利用 引用 a 修改 对象 aObject引用 b 指向的 对象也会跟着改变

因为它们指向的是同一个对象

这就是 浅拷贝 的原理
浅拷贝:拷贝的是对象的引用会受被拷贝对象的影响


那么刚才讲的 和 方法传递有什么关系勒?

好了,不买关子,直接解答:

Java 方法参数传递 就相当于 赋值操作

1. 传入基本类型 参数;
	基本类型
	void A(){
	int i = 2;
		B(i);
	}
	void B(int i){
		i = i + 1;
	}
	// int i = 2;

当 传入参数i,此时B方法中相当于执行了 int i = 2 的操作;

因为栈帧 与 栈帧之间是 “独立”的,因此此刻 方法 A 和 方法 B各自存在一个 i 变量

因此 方法A中的 i 不受影响。

2. 传入引用参数:
	引用类型
	void A(){
	User u = new User(" A ");
		B(u);
	}
	void B(User user){}
	// User user = u == new User(" A ");

此时 u 和 user 都指向堆中 同一个实例对象

因此在方法 B 中向 对象作操作方法A 中的引用也会受到影响

文章开头的bug
	引用类型
	void A(){
	User u = new User(" A ");
		B(u);
	}
	void B(User user){
		user = new User(" B ");
	}

那么此时在 方法B中操作对象, 还会是 方法A中的引用 u 受影响么?

答案是不会;

其实此时方法B 执行了两个操作:

User user = u = new User(" A “);
user = new User(” B ");

很显然,此时的user 已经指向了 堆中的新对象了

此时 你在 B()中,这么改变对象,A()中都不会受影响

而 Arrays.copyof() 底层是深拷贝 返回的就是一个新的数组

深拷贝:拷贝的是对象的不受被拷贝对象的影响


总结

方法传参:
基本类型传递:值传递,深拷贝
引用类型传递:引用传递,浅拷贝

引用类型传递时,注意查看 引用是否在本对象中重新赋值,若出现赋值情况,调用者中引用被调用者中引用 断开连接

好了,今天就说到这里,喜欢笔者的可以点个赞,加个关注。

我将持续更新

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值