通过底层原理理解Java是值传递还是引用传递?

本文学习目标或者巩固的知识点

  • 参数传递方式
    • 值传递
    • 引用传递
    • 指针传递
  • 彻底理解Java的值传递和引用传递
    • 从底层的角度分析
    • 值传递会发生复制行为

Java的参数传递例子

快手的一面面试曾经问到过此类题目,所以记下此篇加深印象。
问:求下面main方法中的输出结果,如果知晓结果则可跳过此篇

public static void main(String[] args) {
    int num = 1;
    值传递_基本类型(num);
    System.out.printf("值传递_基本类型方法结束后=>num=%d \n", num);
    Person person = new Person();
    person.name = "张三";
    引用传递_引用类型(person);
    System.out.printf("引用传递_引用类型方法结束后=>person.name=%s \n", person.name);
}

public static void 值传递_基本类型(int num){
    num = 2;
}
public static void 引用传递_引用类型(Person person){
    person.name = "李四";
}

public static class Person{
    public String name;
}

输出

值传递_基本类型方法结束后=>num=1 
引用传递_引用类型方法结束后=>person.name=李四 

什么是值传递?

百度百科: 值传递是指在调用函数时将 实际参数 复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

Java中基本数据类型:整型(4种)、浮点型(2种)、字符型(1种)、布尔型(1种)。

在赋值操作符(=)的作用下,将变量的值从调用者的作用域传递到被调用的作用域。

对于基本数据类型,复制的是值本身,而不是变量的内存地址。因此,如果一个变量在调用过程中被修改,那么在返回调用者的作用域时,其值仍然是复制时的值。

public static void main(String[] args) {
    int num = 1;
    Integer number = 1;
    char ch = '1';
    Character character = '1';
    值传递_基本类型(num,number,ch,character);
    System.out.printf("值传递_基本类型方法结束后=>num=%d, number=%d, ch=%c, character=%c \n", num, number, ch, character);
}
public static void 值传递_基本类型(int num, Integer number, char ch, Character character){
    num = 2;
    number = 2;
    ch = '2';
    character = '2';
    System.out.printf("值传递_基本类型方法内=>num=%d, number=%d, ch=%c, character=%c \n", num, number, ch, character);
}

值传递_基本类型方法内=>num=2, number=2, ch=2, character=2 
值传递_基本类型方法结束后=>num=1, number=1, ch=1, character=1 

什么是引用传递?

百度百科:所谓 引用传递 是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

在Java中与引用传递相类似的有引用类型的传递(如数组、Object类),在赋值操作符(=)的作用下,将变量的引用指向的对象从调用者的作用域传递到被调用的作用域

对于引用类型,复制的是对象的引用,而不是对象本身。因此,如果一个对象在调用过程中被修改,那么在返回调用者的作用域时,所引用的对象仍然是调用时的对象,但其内容可能会发生变化。比如:如果一个对象包含其他对象作为成员,那么在值传递过程中,只有对象的引用会被复制,而成员对象则不会被复制。这意味着在调用过程中,如果修改了对象内部的成员对象,那么在返回调用者的作用域时,该成员对象可能已经不再是最新的。

值传递:引用数据类型

public static void main(String[] args) {
    int[] arr = new int[1];
    char[] chs = new char[1];
    List<Integer> ls = new ArrayList<>();
    Person person = new Person();
    
    arr[0] = 1;
    chs[0] = '1';
    ls.add(1);
    person.name = "张三";
    
    System.out.printf("引用传递_引用类型方法执行前=> " +
            "\n arr[0]=%d, chs[0]=%c,ls.get(0)=%d, person.name=%s \n", arr[0], chs[0], ls.get(0), person.name);
    
    引用传递_引用类型(arr,chs,ls,person);
    
    System.out.printf("引用传递_引用类型方法结束后=> " +
            "\n arr[0]=%d, chs[0]=%c,ls.get(0)=%d, person.name=%s \n", arr[0], chs[0], ls.get(0), person.name);
}
public static void 引用传递_引用类型(int[] arr, char[] chs, List<Integer> ls, Person personCopy){
    arr[0] = 2;
    chs[0] = '2';
    ls.set(0,2);
    personCopy.name = "李四";
    
    System.out.printf("引用传递_引用类型方法中=> " +
            "\n arr[0]=%d, chs[0]=%c,ls.get(0)=%d, person.name=%s \n", arr[0], chs[0], ls.get(0), personCopy.name);
}
public static class Person{
    public String name;
}

在这里插入图片描述

引用传递_引用类型方法执行前=> 
 arr[0]=1, chs[0]=1,ls.get(0)=1, person.name=张三 
引用传递_引用类型方法中=> 
 arr[0]=2, chs[0]=2,ls.get(0)=2, person.name=李四 
引用传递_引用类型方法结束后=> 
 arr[0]=2, chs[0]=2,ls.get(0)=2, person.name=李四 

通过底层原理理解

堆栈角度解释,Java是值传递。在Java中,当我们将一个变量从调用者的作用域传递到被调用的作用域时,传递的是变量的值(即其值,基本类型叫值,对象叫引用),而不是变量的内存地址。

值传递(基本数据类型传递)图解

对于基本数据类型,Java会进行栈上分配内存,传递的只是一份克隆数据,所以互不影响。

在这里插入图片描述

引用类型传递图解

对于引用数据类型,大部分情况下Java会进行堆上分配内存,栈上的person只是一个引用。person和personCopy是两个引用,但是都指向了同一个地址Person@60215eee,所以对这两个引用的对象内部进行修改导致的影响是一样的。

在这里插入图片描述

检验下你是否真的理解?

public static void main(String[] args) {
    Person person = new Person();
    person.name = "张三";
    System.out.printf("引用传递_引用类型方法执行前=> person.name=%s \n", person.name);
    引用传递_引用类型(person);
    System.out.printf("引用传递_引用类型方法结束后=> person.name=%s \n", person.name);
}
public static void 引用传递_引用类型(Person person){
    person = new Person();
    person.name = "李四";
}
public static class Person{
    public String name;
}

上面的代码【引用传递_引用类型方法结束后=>person.name=】输出什么?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

常用状态码

状态码 用于响应中的&#xff0c;表示响应的结果如何 1、200 OK 运行成功 2、404 Not Found 访问的资源没有找到&#xff08;url的路径&#xff09; 3、403 Forbidden 请求资源没有权限访问 4、405 Method Not Allowed 你的服务器只支持GET请求&#xff0c;但是你发了个PO…

基于springboot+vue的校园社团信息管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

sizeof和strlen的对比及练习题(超详细)

创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ sizeof和strlen的对比 sizeof举例说明 sizeof计算int类型数据 &#xff08;有关于数组&#xff09;sizeof计算 strlen举例说明 strlen是C语言库函数&#xff0c;求字符串长度 函数原型&#xff1a; size_t s…

前端项目打包体积分析与优化

一、安装依赖分析工具 npm install webpack-bundle-analyz 二、修改webpack.config.js文件 1、导入上面下载的包 2、在plugins里创建实例 三、启动打包命令 npm run build 会弹出如下界面&#xff1a; 四、优化 1、通过CDN导入react-dom文件 修改webpack.config.js文件里…

掌握3个Mock工具,轻松玩转单元测试

公司要求提升单元测试的质量&#xff0c;提高代码的分支覆盖率和行覆盖率&#xff0c;安排我研究单元测试&#xff0c;指定方案分享并在开发部普及开。 单元测试中的Mock的目的 Mock的主要目的是让单元测试Write Once, Run Everywhere. 即编写一次后&#xff0c;可以在任意时…

LeetCode--代码详解 236. 二叉树的最近公共祖先

236. 二叉树的最近公共祖先 题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&am…

中国农业无人机行业市场现状分析与投资前景预测研究报告

全版价格&#xff1a;壹捌零零 报告版本&#xff1a;下单后会更新至最新版本 交货时间&#xff1a;1-2天 第一章农业无人机行业发展综述 第一节农业无人机行业定义及分类 一、农业无人机行业的定义 农业无人机是一种无人驾驶的飞行器来帮助优化农业经营&#xff0c;增加作…

找游戏 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 小扇和小船今天又玩起来了数字游戏&#xff0c; 小船给小扇一个正整数 n&#xff08;1 ≤ n ≤ 1e9&#xff09;&#xff0c;小扇需要找到一个比 n 大的数字 m&a…

C++ //练习 8.8 修改上一题的程序,将结果追加到给定的文件末尾。对同一个输出文件,运行程序至少两次,检验数据是否得以保留。

C Primer&#xff08;第5版&#xff09; 练习 8.8 练习 8.8 修改上一题的程序&#xff0c;将结果追加到给定的文件末尾。对同一个输出文件&#xff0c;运行程序至少两次&#xff0c;检验数据是否得以保留。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工…

dolphinscheduler伪集群部署教程

文章目录 前言一、配置免密登录1. 配置root用户免密登录2. 创建用户2.1 创建dolphinscheduler用户2.2 配置dolphinscheduler用户免密登录2.3 退出dolphinscheduler用户 二、安装准备1. 安装条件2. 安装jdk3. 安装MySQL4. 安装zookeeper4.1 zookeeper单机部署4.2 启动zookeeper4…

14-ATF中对多核的支持

讨论一个系统、一个软件或ATF对多核的支持,其实就是看这个软件,在启动阶段如何区分主核、从核的? 在runtime阶段,是否能把不同核的CPU Data加以区分?是否能区分出cpuid? runtime阶段:主核和从核的区分 在启动阶段,会读取平台函数plat_is_my_cpu_primary来判单,当前是…

java 面向对象-上:类的结构之二

类的设计中&#xff0c;两个重要结构之二&#xff1a;方法 方法 描述类应该具的功能。 比如&#xff1a;Math类&#xff1a;sqrt()\random() \... Scanner类&#xff1a;nextXxx() ... Arrays类&#xff1a;sort() \ binarySearch() \ toString() \ equals() \ ... 1.举例 p…

哈希-数组中两数之和

文章目录 题目解题思路具体步骤 题目 在编程和算法学习中&#xff0c;"两数之和"问题是一个非常经典的问题&#xff0c;它不仅测试了基本的编程能力&#xff0c;还涉及到数据结构的有效使用&#xff0c;特别是哈希表。问题的描述是这样的&#xff1a; 题目&#xff…

1110. 删点成林

1110. 删点成林 关键要点 通过O(1)时间复杂度确认节点是否需要删除 Set to_deleteSet new HashSet<>(); Arrays.stream(to_delete).forEach(to_deleteSet::add); 使用深度优先搜索&#xff08;DFS&#xff09;遍历树 node.left dfs(node.left, s, ans); node.right …

Orange3数据预处理(列选择组件)数据角色及类型描述

在Orange3的文件组件中&#xff0c;datetime、categorical、numeric以及text代表不同种类的数据类型&#xff0c;具体如下&#xff1a; datetime&#xff1a;代表日期和时间类型的数据。通常用于时间序列分析、生存分析和其他需要考虑时间因素的机器学习任务中。例如&#xff0…

英语连读技巧15

1. first one – 第一个 连读听起来就像是&#xff1a;【佛斯湾】 连读的音标为&#xff1a; 例句&#xff1a;I don’t want to be the first one there agin. 发音指导&#xff1a;在“first one”的连读中&#xff0c;"t"和"o"之间的连接几乎消失&a…

17.材质和外观

1.图形学中的材质 在图形学中&#xff0c;材质&#xff08;Material&#xff09;是用来描述物体外观和表面特性的属性集合。它包含了控制光的反射、折射、吸收以及其他光学效果的信息&#xff0c;从而决定了物体在渲染过程中的外观。 渲染方程中那一项和材质有关&#xff1f; …

RDMA内核态函数ib_post_recv()源码分析

接上文&#xff0c;上文分析了内核rdma向发送队列添加发送请求的函数ib_post_send&#xff0c;本文分析一下向接收队列添加接收请求的函数ib_post_recv。其实函数调用流程与上文类似&#xff0c;不再重复说明&#xff0c;可参考链接。 函数调用过程 最终会调用到这个函数 下面…

Git笔记——3

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、合并模式和分支策略 二、bug分支 三、强制删除分支 四、创建远程仓库 五、克隆远程仓库_HTTPS和_SSH 克隆远程仓库_HTTPS 克隆远程仓库_SSH 六、向远程仓库…

深入理解计算机系统——内部很重要的硬件

文章目录 计算机的内部硬件系统的硬件组成运行hello高速缓存Cache存储设备的层次结构 计算机的内部硬件 系统的硬件组成 1.总线 简单来说就是字节流在总线里面跑来跑去&#xff0c;通常这个被设计成一个传送定长的字节块&#xff0c;也就是字。 在计算机系统中&#xff0c;字…