【Stackoverflow好问题】Java是按值传递还是按引用传递

本文通过实例详细解析了Java中的按值传递机制,探讨了如何正确理解和使用对象参数,避免常见的编程误区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开始之前,我们先理解按值传递、按引用传递的概念。
1、什么是值传递?
指的是在方法调用时,传递的参数是按值的拷贝传递。按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了,每个值都对应到一个地址空间
2、什么是引用传递
指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

明确地说,java都是按值传递的!java的世界里,都是按值传递。其实按值、按引用都只是个概念,关键是我们如何去理解java传参的本质。
下面就结合一个例子来说
有些情况下,所参数参数的值,是个“引用",这一点容易让人产生困惑。

请看下面的例子
首先有如下代码
Dog myDog = new Dog("Rover");
foo(myDog);
这时,你传给了foo函数一个参数,这个参数值,是个引用,也就是Rover这只dog的内存地址(这只是粗略的说明,因为在java中,这个地址并非是真正的地址)
假设这时候Rover的地址是42,那么,我们就是传了42这个地址给foo方法
public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC}
让我们逐步解析foo方法
1、参数 someDog的值是一个地址(42)
2、在AAA这一行:
someDog,也就是函数外声明的myDog,name从Rover被改成了Max
3、在BBB这一行:
这就是关键的地方了,又new了一只dog,new 意味着又在新的地址空间放上了一只Dog,我们假设其地址是74。这时,someDog的值,会从42变成了74
4、在CCC这一行:
这时候的修改,是对内存地址为74的那只狗的修改,而非原先的42

从这个例子,我们可以看到,foo方法的参数someDog,它是一个值,而非引用。 如果它是引用,那么在foo方法内部的修改(包括BBB、CCC这两行),都应该会对42地址空间的dog产生影响,也就是方法外的参数,mydog也会指向新的地址空间

不细究概念了,再总结下Java初学者容易犯错的地方:
假如你想像例子一样,传递一个对象到一个方法中,并由该方法修改对象。
Object a = new Object();
foo(a);//在方法内部修改a的属性值
return a;//希望此时的a已经是修改后的值

要切记,这个Objct一定要在调用方法前,就初始化好(new一个),然后再作为参数传进去,并且在方法中不能再初始化这个参数。这样,在方法中对该参数的修改,才会有效。


stackoverflow链接
http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value



专栏介绍:
非常喜欢stackoverflow,总能在上面找到疑难杂症的解决办法。偶然发现该网站有一个热度榜单。于是精选了热度较高的一些问题,阅读每个问题的答案,然后按照自己的理解梳理出来。因此,这些文章不是真正的翻译,而是按照自己的理解做了一些增删、润色,希望能把上面的讨论,更精简有效地分享给大家。
如需转载,请注明原文地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值