从JVM的角度,来分析为什么Java中是值传递?

从 JVM 的角度来看,Java 中的参数传递之所以是值传递,是因为在 JVM 执行方法调用时,参数的值(不论是基本类型还是引用类型)都被复制并压入调用栈的帧(stack frame)中。让我们从 JVM 的内存模型和调用栈的角度,详细分析为什么 Java 中是值传递。

1. JVM 的内存模型

JVM 的内存分为几个重要区域,其中与方法调用和参数传递相关的主要有:

  • 堆(Heap):用于存储对象实例。所有对象都存储在堆中,所有引用类型(如 StringList 等)变量其实是指向堆中对象的引用。
  • 栈(Stack):用于存储方法调用的局部变量和临时数据,每个线程都有一个自己的栈。当方法被调用时,JVM 会在栈中为这个方法分配一个新的栈帧(stack frame)来保存方法的参数、局部变量和一些临时数据。

2. 方法调用和栈帧

当方法被调用时,JVM 会在栈中为这个方法创建一个新的栈帧。这个栈帧包含:

  • 参数值的副本:方法的每一个参数(不管是基本类型还是引用类型)都会被复制一份,并存储在栈帧中。
  • 局部变量:方法内定义的局部变量也会存储在栈帧中。

栈帧在方法执行完毕后会被弹出栈,并释放所有数据。

3. 值传递的工作原理

当方法被调用时,JVM 会根据传入的参数创建它们的副本:

  • 基本类型参数(如 intdouble 等):直接将参数的值复制一份,并将这个值存储到栈帧中。
  • 引用类型参数(如 StringArrayList 等):传递的实际上是引用的副本。引用本身是一个指向堆中对象的地址(即对象的内存位置),这个地址值被复制并存储到栈帧中。

这意味着:

  • 基本类型:在方法内部对参数的修改只会影响副本,不会影响原始变量。
  • 引用类型:传递的是引用的副本,因此在方法内部可以通过这个副本引用操作对象本身,但如果修改引用的指向(让引用指向新的对象),不会影响原始的引用。

举例分析:基本类型的值传递

public class Test {public static void main(String[] args) {int x = 5;modify(x);System.out.println(x); // 输出:5}public static void modify(int num) {num = 10;}
}
  • modify(x) 被调用时,x 的值(即 5)被复制一份并传递给 num,此时 num 变量的值是 5
  • modify 方法中,将 num 的值改为 10,但这不会影响 main 方法中的 x,因为 num 只是 x 的副本。
  • JVM 机制:在 modify 方法的栈帧中,num 存储了 5 的副本。当方法执行完后,栈帧被销毁,num 消失,x 的值仍然是 5

举例分析:引用类型的值传递

import java.util.ArrayList;
import java.util.List;public class Test {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("A");modify(list);System.out.println(list); // 输出:[A, B]}public static void modify(List<String> lst) {lst.add("B");}
}
  • modify(list) 被调用时,list 引用(地址)被复制一份,并传递给 lst
  • listlst 都指向堆中同一个 ArrayList 对象。
  • JVM 机制:在 modify 方法的栈帧中,lstlist 引用的副本,因此 lstlist 指向同一个对象。对 lst 的操作(如 lst.add("B"))会影响原始对象。

为什么即使是引用类型,Java 仍是值传递?

这是因为在 JVM 中,即使是引用类型,传递的仍然是引用的副本,而不是引用本身的地址引用。

  1. 引用的副本:在方法调用中,引用类型的参数传递的是引用的值,即指向对象的内存地址。这意味着方法内部的引用与外部的原始引用是不同的变量,只是它们指向同一个对象。
  2. 修改引用指向:如果在方法内部将引用重新赋值(让它指向另一个新对象),这种修改只会影响方法内部的引用,不会影响外部的原始引用。这进一步验证了 Java 是按值传递的,因为重新赋值并不影响原始对象的引用。

例如:

public class Test {public static void main(String[] args) {StringBuilder sb = new StringBuilder("Hello");modify(sb);System.out.println(sb); // 输出:Hello}public static void modify(StringBuilder sb) {sb = new StringBuilder("Goodbye"); // 重新赋值,原始对象不受影响}
}

modify 方法中,将 sb 重新赋值为一个新对象,这不会影响 main 方法中的 sb,因为 modify 方法中的 sb 只是原始引用的副本,重新赋值只影响副本。

总结

从 JVM 的角度,Java 是值传递,因为:

  1. 参数复制到栈帧:方法调用时,所有参数的值(无论是基本类型的值还是引用类型的地址)都被复制到新建的栈帧中。这些值的副本和原始值是独立的。
  2. 引用类型传递的是地址的副本:对于引用类型,传递的是指向对象的地址(引用)的副本,方法内部可以通过这个副本引用修改对象的内容,但不能改变原始引用本身。
  3. Java 中没有按引用传递:在 Java 中,不存在直接传递对象引用地址的情况,始终是传递的值的副本。

这种实现方式确保了 Java 的方法调用是“安全”的,不会因为方法内部的参数操作而直接改变调用方的变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/59526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity自动LOD工具AutoLOD Mesh Decimator的使用

最近在研究大批量物体生成&#xff0c;由于我们没有专业美术&#xff0c;在模型减面工作上没有人手&#xff0c;所以准备用插件来实现LOD功能&#xff0c;所以找到了AutoLOD Mesh Decimator这个插件。 1&#xff0c;导入插件后&#xff0c;我们拿个实验的僵尸狗来做实验。 空…

爬虫补环境案例---问财网(rpc,jsdom,代理,selenium)

目录 一.环境检测 1. 什么是环境检测 2.案例讲解 二 .吐环境脚本 1. 简介 2. 基础使用方法 3.数据返回 4. 完整代理使用 5. 代理封装 6. 封装所有使用方法 jsdom补环境 1. 环境安装 2. 基本使用 3. 添加参数形式 Selenium补环境 1. 简介 2.实战案例 1. 逆向目…

免费,WPS Office教育考试专用版

WPS Office教育考试专用版&#xff0c;不仅满足了考试需求&#xff0c;更为教育信息化注入新动力。 https://pan.quark.cn/s/609ef85ae6d4

Vue前端开发,组件及组件的使用

什么是组件 组件(Component)是Vue中最强大的功能之一&#xff0c;每个Vue 文件就是一个个独立的组件&#xff0c;组件也可以被其他组件调用&#xff0c;形成嵌套关系&#xff0c;大部分的应用都是由各类不同功能的小组件进行构建&#xff0c;形成一个功能强大的大组件树系统&a…

政务数据治理专栏开搞!

写在前面 忙忙碌碌干了一年政务数据治理的工作&#xff0c;从法人数据到自然人&#xff0c;从交通到地理信息等等&#xff0c;突发想法开一个专栏讲一讲政务数据遇到的问题&#xff0c;以及治理的成效&#xff0c;或许有朋友爱看。 政务数据&#xff0c;又称之为政务数据资源&a…

前端在PC端实现支付思路流程

一.去支付 1.前端点击“去支付”按钮&#xff0c;请求订单详情接口&#xff0c;传递订单的id、订单号给后端和请求支付方式接口 2.后端返回支付信息和支付方式数据 二.弹出支付窗口 接收支付信息和支付方式数据后&#xff0c;前端弹出支付弹窗 三.确认支付 前端无论选择任何…

VUE3实现好看的世界建筑中国建筑网站源码

文章目录 1.设计来源1.1 网站主界面1.2 登录界面1.3 注册界面1.4 特色建筑展览界面1.5 世界建筑介绍界面1.6 世界建筑介绍 - 详情界面1.7 中国建筑介绍界面1.8 中国建筑介绍 - 详情界面1.9 关于我们界面 2.效果和源码2.1 动态效果2.2 源代码2.3 目录结构 源码下载万套模板&…

「人眼视觉不再是视频消费的唯一形式」丨智能编解码和 AI 视频生成专场回顾@RTE2024

你是否想过&#xff0c;未来你看到的电影预告片、广告&#xff0c;甚至新闻报道&#xff0c;都可能完全由 AI 生成&#xff1f; 在人工智能迅猛发展的今天&#xff0c;视频技术正经历着一场前所未有的变革。从智能编解码到虚拟数字人&#xff0c;再到 AI 驱动的视频生成&#…

「QT」文件类 之 QTemporaryFile 临时文件类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制…

和 Nostr 探索 Web5 的未来

Nostr 是一个我过去两年一直在关注的协议。跟所有社区一样&#xff0c;Nostr 的发展也是起起伏伏&#xff0c;有过一些破圈被主流熟悉的时刻&#xff0c;也有一些像现在这样可能让人会觉得有点沉寂的时刻。但我还是经常关注 Nostr&#xff0c;没有特别的原因&#xff0c;就是单…

论文学习——一种基于决策变量分类的动态约束多目标进化算法

论文题目&#xff1a; A dynamic constrained multiobjective evolutionary algorithm based on decision variable classification 一种基于决策变量分类的动态约束多目标进化算法&#xff08;Yinan Guo a,b, Mingyi Huang a, Guoyu Chen a,*, Dunwei Gong c, Jing Liang d, …

数据分析案例-笔记本电脑价格数据可视化分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

第T7周:Tensorflow实现咖啡豆识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: &#xff08;二&#xff09;具体步骤 1. 使…

vue2项目中在线预览csv文件

简介 希望在项目中&#xff0c;在线预览.csv文件&#xff0c;本以为插件很多&#xff0c;结果都只是支持excel&#xff08;.xls、.xlsx&#xff09;一到.csv就歇菜。。。 关于文件预览 vue-office&#xff1a;文档、 查看在线演示demo&#xff0c;支持docx、.xlsx、pdf、ppt…

【Excel】身份证号最后一位“X”怎么计算

大多数人身份证号最后一位都是数字&#xff0c;但有个别号码最后一位却是“X"。 如果你查百度&#xff0c;会得到如下答案&#xff1a; 当最后一位编码是10的时候&#xff0c;因为多出一位&#xff0c;所以就用X替换。 可大多数人不知道的是&#xff0c;这个10是怎么来的…

【HAProxy09】企业级反向代理HAProxy高级功能之压缩功能与后端服务器健康性监测

HAProxy 高级功能 介绍 HAProxy 高级配置及实用案例 压缩功能 对响应给客户端的报文进行压缩&#xff0c;以节省网络带宽&#xff0c;但是会占用部分CPU性能 建议在后端服务器开启压缩功能&#xff0c;而非在HAProxy上开启压缩 注意&#xff1a;默认Ubuntu的包安装nginx开…

【Java Web】JSON 以及 JSON 转换

JSON&#xff08;JavaScript Object Notation&#xff09;一种灵活、高效、轻量级的数据交换格式&#xff0c;广泛应用于各种数据交换和存储场景。 基本特点 1、简单易用&#xff1a;JSON格式非常简单&#xff0c;易于理解和使用。 2、轻量级&#xff1a;相比XML等其他数据格…

第四十一章 Vue之初识VueX

目录 一、引言 1.1. vuex的概念 1.2. vuex使用场景 1.3. 优势 二、创建演示项目 2.1. 构建项目步骤 2.2. 项目最终生成结构 2.3. 创建项目文件 2.3.1. App.vue 2.3.2. Son1.vue 2.3.3. Son2.vue 三、创建一个空仓库 3.1. 安装vuex 3.2. 新建仓库 3.3. 挂载仓库…

编程之路,从0开始:内存函数

Hello大家好&#xff01;很高兴我们又见面了。 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 今天我们来讲C语言中的内存函数。 目录 1、memcpy内存复制 2、memmove可重叠内存拷贝 3、memset设置字符 4、memcmp比较 1、memcpy内存复制 memcpy就是内存复制…

【C语言】值传递和地址传递

值传递 引用传递&#xff08;传地址&#xff0c;传引用&#xff09;的区别 传值&#xff0c;是把实参的值赋值给行参 &#xff0c;那么对行参的修改&#xff0c;不会影响实参的值。 传地址&#xff0c;是传值的一种特殊方式&#xff0c;只是他传递的是地址&#xff0c;不是普通…