秒懂Java为什么只有值传递
在Java语言中,数据类型分为基本数据类型和引用数据类型。
基本数据类型(如int、double、char等)的值直接保存在栈上。这些类型的变量在栈内存中有固定的大小,并且值是直接存储在这些变量中的,数据的传递为值传递,这个好理解。以下以引用数据类型来讲解。
引用和实例化对象
比如new一个对象的代码:等号左边的person为引用;等号的右边new Person()为实例化对象。
Person person = new Person();
引用 = 实例化对象
引用和实例化对象在内存中,分别保存在栈和堆中。引用会保存着实例化对象的地址,从而可以通过引用来获取到具体的实例化对象保存在哪里。
关系如图:

值传递和引用传递
顾名思义,值传递是把“值”传递到方法中,而引用传递是把“引用”传递到方法中。
在Java 的参数传递方式中,只有值传递。对于引用对象也是值传递,而这个值是引用的值(即堆地址或句柄)被拷贝传递到方法中。
文字太抽象了,看图和代码:


对比两者
值传递
源引用地址:0x0a --> 对象地址:0x10
传递时:新引用地址:0x0b --> 对象地址:0x10
引用传递
源引用地址:0x0a --> 对象地址:0x10
传递时:方法中仍是引用地址:0x0a --> 对象地址:0x10
值传递:是复制一份“引用”传给方法的形参,person 和 person2 是两个不同的栈内存地址(如 0x0a和0x0b)
引用传递:是将实参的引用直接传给方法的形参,person 和 person2 实际共享了相同的栈内存地址(如 0x0a)
两者有着本质的区别!对比两者的行为和带来的影响。
对比示意图
| 行为 | 值传递(Java 的实际行为) | 引用传递(假设机制) |
|---|---|---|
| 方法参数接收到的值 | 引用地址的副本(如 0x0b) |
原始引用地址本身(如 0x0a) |
| 引用的改变影响范围 | 改变方法内的引用指向,不影响原始引用 | 改变引用指向会影响原始引用 |
| 对象属性的修改 | 通过引用修改对象属性,会影响原始对象 | 通过引用修改对象属性,会影响原始对象 |
代码验证
测试代码:测试引用的改变影响范围和对象属性的修改
public class ValuePassDemo {
public static void main(String[] args) {
Person person = new Person();
person.setAge(18);
person.setName("Denny");
// 初始值
System.out.println("地址:"+ Integer.toHexString(person.hashCode()) + ">>>" + person);
modifyReference(person);
// 是否会被上一个方法修改值
System.out.println("地址:"+ Integer.toHexString(person.hashCode()) + ">>>" + person);
modifyReference2(person);
// 是否会被上一个方法修改值
System.out.println("地址:"+ Integer.toHexString(person.hashCode()) + ">>>" + person);
}
/**
* 形参和实参引用指向的实例化对象是同一个
* 实例化对象的值被任意一边修改时,都会改变
*/
public static void modifyReference(Person person2) {
person2.setAge(28);
person2.setName("Jack");
System.out.println("地址:"+ Integer.toHexString(person2.hashCode()) + ">>>" + person2);
}
/**
* 如果是引用传递,
* 那实参引用 person 等于形参引用 person2,
* 那么引用 person2 的指向被改变的话,形参引用 person也会指向新的实例化对象
* 如果不成立,那就是值传递,引用person2 只是引用person的拷贝,而非本身给了它
*/
public static void modifyReference2(Person person2) {
person2 = new Person();
person2.setAge(20);
person2.setName("apple");
System.out.println("地址:"+ Integer.toHexString(person2.hashCode()) + ">>>" + person2);
}
}
测试结果:

方法内部修改引用的指向
调用modifyReference2方法,会给形参变量赋一个新的实例化对象的情况,
如果是值传递,形参和实参分别指向不同的实例化对象,如图:

如果是引用传递,形参和实参都指向相同的实例化对象,而原来的实例化对象就没有引用指向。
如图:

原来的实例化对象没有引用指向,会导致内存泄漏,用C++的语言描述:按引用传递时,并且在方法内修改引用指向新new的对象时,需要手动释放内存。
void myFunction(Person* obj)是按值传递。void myFunction(Person*& obj)是引用传递。
void myFunctionWithReference(Person*& obj) {
delete obj; // 先释放原对象的内存
obj = new Person(20); // 重新分配新的对象,并让 obj 指向它
}
为什么Java只有值传递
个人觉得Java 选择只有值传递的参数传递机制(pass-by-value)目的应该包含:内存安全性、简化内存管理、保持语言行为一致性和语言简单易用。
这也是Java语言的优点,弱化对内存操作的概念,让这门语言更加简洁易用;同时这也是Java语言的缺点,降低了灵活性,无法直接通过方法修改引用变量的指向。

秒懂Java为什么只有值传递的更多相关文章
- Java 中的值传递和参数传递
Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能 值传递:方法调用时,实际参数 ...
- Java中的值传递和引用传递
这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...
- java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解(勿删)
head first java里写到“java是通过值传递的,也就是通过拷贝传递”,由此得出结论,方法无法改变调用方传入的参数.该怎么理解呢? 看例子: public class Test1 { pu ...
- Java中的值传递
1.先比较下字符串的比较 == 代表全等于 值和地址(存放地址) 全部相等于. equals 值等于== 和 equals的区别 列如下面的 如果name1==name2是等于的 然而name1==n ...
- 为什么说Java中只有值传递
本文转载自公众号 Hollis 对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文 ...
- 一道笔试题来理顺Java中的值传递和引用传递
题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...
- java中的值传递和引用传递有什么区别呀?
值传递: (形式参数类型是基本数据类型和String):方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参 ...
- 为什么说Java中只有值传递(转载)
出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...
- 为什么说Java中只有值传递?
一.为什么说Java中只有值传递? 对于java中的参数传递方式中是否有引用传递这个话题,很多的人都认为Java中有引用传递,但是我个人的看法是,Java中只有值传递,没有引用传递. 那么关于对象的传 ...
- JAVA中只有值传递
今天,我在一本面试书上看到了关于java的一个参数传递的问题: 写道 java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? 我毫无疑问的回答:“引用传递!”,并且还觉得自己对java的这 ...
随机推荐
- zabbix-server无法启动
部署:Zabbix-(1)安装 - xiao智 - 博客园 (cnblogs.com) 故障现象: 监控界面状态为 "否" 1.服务状态果然报错了 ,报错提示是被退出的 2.net ...
- ZEGO 自研客户端配置管理系统 —— 云控
一.常规客户端配置的弊端 客户端配置信息通常会通过一个静态文件进行管理,或存放在本地或者通过远程获取.存在本地最大的问题是不易更新,所以通常做法是通过远程获取. 我们通过两种常见的场景来看看静态文件管 ...
- 【笔记】利用七牛云CDN加速提高前端图片静态资源访问速率
第一步,注册七牛云账号 打开 七牛开发者平台,选择 注册,注册后登录系统然后实名认证. 第二步,创建七牛云空间 七牛对象存储将数据文件以资源的形式上传到空间中.您可以创建一个或者多个空间,然后向每个空 ...
- JavaScript – Sort
前言 排序是很常见的需求. 虽然看似简单, 但其实暗藏杀机. 一不小心就会搞出 Bug 哦. 这篇就来聊聊 JS 的排序. 参考 原生JS数组sort()排序方法内部原理探究 值的比较 js中的loc ...
- OData – API Versioning
前言 先看这 3 篇 ASP.NET Core – Web API Versioning ASP.NET Core – Swagger OpenAPI (Swashbuckle) ASP.NET Co ...
- DTO转VO工具
data工具,实现了对象拷贝 DTO -> VO 只需要实现一个类即可 data-utils data工具,实现了对象拷贝DTO -> VO 解决的问题 Mapstruct需要安插件!!! ...
- Vue3——SVG 图标配置
1. SVG 图标配置 安装 SVG 依赖插件 vite-plugin-svg-icons npm i vite-plugin-svg-icons -D npm install fast-glob - ...
- Java实现随机抽奖的方法有哪些
在Java中实现随机抽奖的方法,通常我们会使用java.util.Random类来生成随机数,然后基于这些随机数来选择中奖者.以下将给出几种常见的随机抽奖实现方式,包括从数组中抽取.从列表中抽取以及基 ...
- Java日期时间API系列15-----Jdk8中java.time包中的新的日期时间API类,java日期计算2,年月日时分秒的加减等
通过Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析 ,可以看出java8设计非常好,实现接口Temporal, Tempora ...
- pcss 软阴影
PCF Percentage Closer Filtering:PCF是一种用于阴影反锯齿的方法,本身不是软阴影方法. 算法流程说明: Perform multiple (e.g. 7x7) dept ...