Java到底是值传递还是引用传递【通俗易懂】

我相信很多刚学Java的小伙伴都很难理解Java到底是值传递还是引用传递的问题,但肯定背过这道面试题。确实,Java就是值传递,那什么原理呢?请往下看。

我们先看一段代码:分析一下这两句打印的结果分别是什么。

public class Test {public static void main(String[] args) {double percent = 10;tripleValue(percent);System.out.println("percent的值为:" + percent);}public static void tripleValue(double x){x = 3 * x;System.out.println("x的值为:" + x);}
}
x的值为:30.0
percent的值为:10.0

可能有小伙伴会问了,我明明将变量percent传到tripleValue方法中了,并在方法内,将值乘以了3,那x和percent的值都应该是30.0啊?

嗯,按逻辑讲确实是这样,但Java却不是这么做的,它在你传参的时候,偷偷的将percent变量拷贝了一个“副本”,也就是x,后面再用3 * x的时候,其实乘以的是副本,早就不是你传的percent变量了,等tripleValue方法结束,参数变量x就被干掉了。

那么肯定又有小伙伴问了,你基本数据类型勉强算你过关,那我传个Java对象总能破你的局了吧,我就不信传一个对象地址,你还没影响?

嗯,还真是有影响,但你还破不了我的局,请看如下代码,假如我想将员工的工资提高三倍(如果这个员工是我就好了):

public class Test {public static void main(String[] args) {Employee e = new Employee(); //创建员工对象e.setSalary(10.0); //设置e员工的工资为10tripleSalary(e);System.out.println("e的工资为:" + e.getSalary());}public static void tripleSalary(Employee x){double addSalary = x.getSalary() * 3; //为员工涨工资x.setSalary(addSalary);System.out.println("x的工资为:" + x.getSalary());}
}
x的工资为:30.0
e的工资为:30.0

从结果上来看,实现方法改变对象参数的状态是完全可以的。理由也很简单,方法得到的是对象引用的“副本”,原来的对象引用和这个副本都引用同一个对象,就类似于这样:

在传参的时候,依然搞了一个副本x,但x和e指向的是同一个对象地址,所以x改了,e也改。

我们再通过一个例子来让你完全理解到底是值传递还是引用传递,下面来编写一个交换两个 Employee 对象的方法:

public static void swap(Employee x, Employee y){Employee temp = x;x = y;y = temp;
}

如果 Java 对对象采用的是按引用调用,那么这个方法就应该能够实现交换:

Employee a = new Employee();
Employee b = new Employee();
System.out.println("a的地址值为:" + a);
System.out.println("b的地址值为:" + b);
swap(a, b);
System.out.println("交换后a的地址值为:" + a);
System.out.println("交换后b的地址值为:" + b);
a的地址值为:com.example.test.controller.Employee@5caf905d
b的地址值为:com.example.test.controller.Employee@27716f4
交换后a的地址值为:com.example.test.controller.Employee@5caf905d
交换后b的地址值为:com.example.test.controller.Employee@27716f4

从结果上看出,a和b并没有实现交换,其实原因很简单,在传递参数的过程中,还是拷贝了两个副本,a的副本是x,b的副本是y,方法中交换的也是x和y交换,压根没a和b什么事,所以可以得出结论,Java是值传递。

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

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

相关文章

R3LIVE源码解析(9) — R3LIVE中r3live_lio.cpp文件

目录 1 r3live_lio.cpp文件简介 2 r3live_lio.cpp源码解析 1 r3live_lio.cpp文件简介 在r3live.cpp文件中创建LIO线程后,R3LIVE中的LIO线程本质上整体流程和FAST-LIO2基本一致。 2 r3live_lio.cpp源码解析 函数最开始会进行一系列的声明和定义,发布的…

前端面试基础面试题——5

1.react 和 vue 的区别是什么? 2.虚拟DOM的原理?优点与缺点? 3.类组件和函数组件之间的区别是? 4.state 和 props 区别是什么? 5.React 中 refs 是做什么的? 6.什么是高阶组件? 7.讲讲什么…

重装系统后,MySQL install错误,找不到dll文件,或者应用程序错误

文章目录 1.找不到某某dll文件2.mysqld.exe - 应用程序错误使用DX工具直接修复 1.找不到某某dll文件 由于找不到VCRUNTIME140_1.dll或者MSVCP120.dll,无法继续执行代码,重新安装程序可能会解决此问题。 在使用一台重装系统过的电脑,再次重新…

ModStartCMS v7.2.0 匿名点赞功能,注册站内信

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议,免费且不限制商业使用。 功能特性 丰富的模块市…

elementUI时间选择器

<template>//月选择器//:clearable"false" 去掉<div class"monthCard"><el-date-picker:clearable"false"v-model"monthValue"type"month"placeholder"选择月"change"handleChangeMonth($eve…

音频——硬件拓扑

文章目录 硬件拓扑I2S 数据通路五线模式四线模式两线 TX两线 RX 典型应用硬件连接数据流 硬件拓扑 控制路径&#xff1a;UART/I2C/SPI数据路径&#xff1a;I2S 简略图如下 I2S 数据通路 五线模式 四线模式 两线 TX 两线 RX 典型应用 硬件连接 控制信号&#xff1a;SPI 用…

Flask狼书笔记 | 05_数据库

文章目录 5 数据库5.1 数据库的分类5.2 ORM5.3 使用Flask_SQLAlchemy5.4 数据库操作5.5 定义关系5.6 更新数据库表5.7 数据库进阶小结 5 数据库 这一章学习如何在Python中使用DBMS&#xff08;数据库管理系统&#xff09;&#xff0c;来对数据库进行管理和操作。本书使用SQLit…

SPI协议

文章目录 前言一、简介1、通信模式2、总线定义3、SPI通信结构4、SPI通讯时序5、SPI数据交互过程 二、多从机模式1、多NSS2、菊花链3、SPI通信优缺点4、UART、IIC、SPI 区别 三、总结四、参考资料 前言 SPI协议是我们的重要通信协议之一&#xff0c;我们需要掌握牢靠。 一、简介…

Oracle Merge Into ORA-00001: unique constaint violated问题

最近使用Datax同步进行定时数据同步&#xff0c;并在同步完之后进行回调sql进行统计操作。对应的ORACLE表结构如下&#xff1a; create table DATA_STAT_DAY ( DATA_DATE DATE, ID VARCHAR2(2), NAME VARCHAR2(2), CLASSNO VARCHAR2(2), SCORES NUMBER(16,0) );CREATE UNIQU…

postgis数据库导出csv表再导入postgis

1、导出csv表 from settings_Address import * from sqlalchemy import create_engine, MetaData import pandas as pd def create_conn(Postgis_user,Postgis_password,Postgis_host,Postgis_port,dbname_PG):# return create_engine(PostgispyPostgis://{}:{}{}:{}/{}.forma…

Mysql 流程控制

简介 我们可以在存储过程和函数中实现比较复杂的业务逻辑&#xff0c;但是需要对应的流程控制语句来控制&#xff0c;就像Java中分支和循环语句一样&#xff0c;在MySQL中也提供了对应的语句&#xff0c;接下来就详细的介绍下。 1.分支结构 1.1 IF语句 IF 表达式1 THEN 操作1…

Android MQTT:实现设备信息上报与远程控制

Android MQTT&#xff1a;实现设备信息上报与远程控制 1. 介绍 1.1 MQTT是什么&#xff1f; MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的消息传输协议&#xff0c;最初由IBM开发&#xff0c;用于连接远程设备与服务器之间的通信。它在物…

尚硅谷SpringMVC (9-13)

九、HttpMessageConverter HttpMessageConverter &#xff0c;报文信息转换器&#xff0c;将请求报文转换为 Java 对象&#xff0c;或将 Java 对象转换为响应报文 HttpMessageConverter提供了两个注解和两个类型&#xff1a; RequestBody &#xff0c; ResponseBody &#xff…

【AI创作助手使用测试】C++使用场景生成、Windows设备驱动开发介绍、调试技巧

C 是一种通用的编程语言&#xff0c;具有高性能、高效率、高可维护性等优点&#xff0c;被广泛应用于以下场景&#xff1a; 操作系统和嵌入式系统开发&#xff1a;C 是编写操作系统和嵌入式系统的主要语言之一&#xff0c;它可以提供底层的控制和资源管理&#xff0c;并且具有高…

手写Mybatis:第20章-Mybatis 框架源码10种设计模式分析

文章目录 一、类型&#xff1a;创建型模式1.1 工厂模式1.2 单例模式1.3 建造者模式 二、类型&#xff1a;结构型模式2.1 适配器模式2.2 代理模式2.3 组合模式2.4 装饰器模式 三、类型&#xff1a;行为型模式3.1 模板模式3.2 策略模式3.3 迭代器模式 一、类型&#xff1a;创建型…

代码随想录算法训练营day56 | LeetCode 583. 两个字符串的删除操作 72. 编辑距离

583. 两个字符串的删除操作&#xff08;题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台&#xff09; 思路&#xff1a;实际上就是求两个字符串的最长公共子序列。或者也可以换成编辑距离的理解思路&#xff08;这种就是直接用动…

Python生成器和迭代器

Python的生成器是一种特殊的函数&#xff0c;它可以在迭代过程中动态生成值&#xff0c;而不是一次性生成所有值。生成器使用yield语句来产生一个值&#xff0c;并且在每次调用时暂停执行&#xff0c;保留当前的状态。当再次调用生成器时&#xff0c;它会从上次暂停的地方继续执…

HashMap源码分析(JDK1.8)

概述 JDK 1.8 对 HashMap 进行了比较大的优化&#xff0c;底层实现由之前的 “数组链表” 改为 “数组链表红黑树”&#xff0c;本文就 HashMap 的几个常用的重要方法和 JDK 1.8 之前的死循环问题展开学习讨论。 JDK 1.8 的 HashMap 的数据结构如下图所示&#xff0c;当链表节…

SQL中CONVERT()函数用法详解

SQL中CONVERT函数格式: CONVERT(data_type,expression[,style]) 参数说明: expression 是任何有效的 Microsoft SQL Server™ 表达式。。 data_type 目标系统所提供的数据类型&#xff0c;包括 bigint 和 sql_variant。不能使用用户定义的数据类型。 length nchar、nva…

Elasticsearch Head的使用

目录 概述一、安装 Elasticsearch Head二、解压文件三、安装Elasticsearch Head依赖四、启动 Elasticsearch Head五、修改Elasticsearch Head启动端口号六、使用 Elasticsearch Head注意事项 概述 Elasticsearch Head 是一个用于管理和监控 Elasticsearch 集群的 Web 界面工具…