边实验边分析 - 破解Java参数传递的奥秘(值传递?引用传递?)

本文探讨了Java中参数传递的特性,通过实例分析了基本类型和对象的区别。对于基本类型,Java进行值传递,局部变量的变化不会影响原始值;而对于对象,虽然看似引用传递,实际上是副本引用的修改。理解这一机制有助于避免编程中的误解和错误。
摘要由CSDN通过智能技术生成

边实验边分析 - 破解Java参数传递的奥秘(值传递?引用传递?)

对于Java的这个知识点,我觉得大家可能会有时候会模糊,我在之前就因为对这个知识点的理解不到位,导致了在开发测试过程中的偏差,感觉自己的水平被同事误判了的,所以定下心来研究了下这个知识点,自己总结了一下,不过这个知识点其实没有一个标准的答案,全都在于自己的理解,理解到位了,则不会有大问题,理解不到位,可能就会出现看起来很低级的错误。

所以本篇文章也不是要说明到底是哪一种,只是分享一下我对这个问题的理解,方便大家对这个问题的理解,因为深究这个问题是没有意义的,全看大家的看法而已。

我们先来看一个例子,

private void changeInt(int localI){
    localI = 1;
}
    
int i = 0;
changeInt(i);
Log.d("DemoActivity!", "i == " + i);

运行结果

D/DemoActivity!: i == 0

可以看到,i的值没有依照我们在changeInt方法中对其的改变而改变,我们来分析下这段行为
首先我们需要了解到一个重要的概念,也是这个问题点的一个核心的地方,就是Java在内存中存储变量时候遵循的规则

1.局部变量像基本类型和对象引用是在栈内存中创建的。
2.而真正的对象在堆内存上创建。

上述例子中,在changeInt方法执行的时候,按照上面的规则,localI是一个局部变量,并且是基本类型,所以其会存放在changeInt方法的方法栈中,并且会将i的值复制到localI中,这时候如果我们修改localI的值,等到该方法结束退出的时候,localI就被释放了,最终不会影响到i的值

我们可以使用debug,来证实一下上面的说法,

初始化i=0
在这里插入图片描述
localI为0
在这里插入图片描述
localI值改变为1
在这里插入图片描述
并未改变i的值
在这里插入图片描述

我们再来看另一个例子


class CoreType {
    public int id;
    public String displayName;
    public String coreTypeString;

    public CoreType(int id, String displayName, String coreTypeString) {
        this.id = id;
        this.displayName = displayName;
        this.coreTypeString = coreTypeString;
    }

    @Override
    public String toString() {
        return displayName;
    }
}

private void changeType(CoreType localType){
	localType.id = 100;
	localType.displayName = "123";
	localType = null;
}

CoreType type = new CoreType(0, "", "");
type.displayName = "111";
changeType(type);
Log.d("DemoActivity!", "ct.id == " + type.id + " ct.name == " + type.displayName);

这次我们传入的是一个对象,这个对象里面有一个int值和一个String值的两个变量,我们给与其初始值,然后在changeType中去修改值,并且我们直接把这个对象置为null

运行结果

D/DemoActivity!: ct.id == 100 ct.name == 123

可以看到,这次的值都被替换掉啦,这是什么原因呢,我们来分析一下
首先创建了一个ct对象,其本身是存放在栈上的,因为其本身也是个局部变量,但是其存放的只是一个内存的引用地址,这个引用地址指向堆中,所以对象真正被存放在堆中,接下来我们调用changeType方法,传入了该对象,在方法中,系统一样会在栈上创建出localType对象,但这个localType对象的地址指向的内存其实是和type对象指向的地址是一样的,所以我们对localType中的属性的修改其实就等于对type对象的修改,而我们最后将localType置为null却是没有意义的,因为localType只是一个局部变量,把它置为null也只是将其与指向堆内存的地址切断了,但是并不会影响到type和其指向的堆内存的链接关系,当方法调用结束后,localType对象就从栈中释放了

我们来使用debug验证一下

内存地址为11921
在这里插入图片描述
localType的内存地址也为11921,并改变localType的值
在这里插入图片描述
将localType置为null
在这里插入图片描述
type内的值改变,但type不为null
在这里插入图片描述
可以看到,其地址指向的是同一块地方

其他的类型大家也可以尝试一下,基本类型会和第一个例子一样,而对象则会和第二个例子一样,所以关键点在于java在处理这两种类型的局部变量上的不同,基本类型直接存的是值的拷贝,而对象存放的是地址的拷贝,至于要说是是值传递还是引用传递的,那还真是看个人理解了,不过,如果是和c++比较的话,那我觉得Java应该是属于值传递的,因为c++有真正的引用传递,相信熟悉c++的同学知道,可以通过"&"符号来定义一个参数其为一个引用

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡爾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值