【️Java是值传递还是引用传递?】

在这里插入图片描述

✅Java是值传递还是引用传递?

  • ✅Java是值传递还是引用传递?
    • ✅典型理解
  • ✅增加知识仓
    • ✅Java的求值策略
    • ✅Java中的对象传递
    • ✅值传递和共享对象传递的现象冲突吗?
  • ✅总结

✅Java是值传递还是引用传递?

✅典型理解

编程语言中需要进行方法间的参数传递,这个传递的策略叫做求值策略

在程序设计中,求值策略有很多种,比较常见的就是值传递和引用传递

值传递和引用传递最大的区别是传递的过程中有没有复制出一个副本来,如果是传递副本,那就是值传递,否则就是引用传递。

Java对象的传递,是通过复制的方式把引用关系传递了,因为有复制的过程,所以是值传递,只不过对于Java对象的传递,传递的内容是对象的引用。

✅增加知识仓

✅Java的求值策略

前面我们介绍过了传值调用、传引用调用以及传值调用的特例传共享对象调用,那么,Java中是采用的哪种求值策略呢?

很多人说Java中的基本数据类型是值传递的,这个基本没有什么可以讨论的,普遍都是这样认为的.。

但是,有很多人却误认为Java中的对象传递是引用传递。之所以会有这个误区,主要是因为Java中的变量和对象之自是有引用关系的。Java语言中是通过对象的引用来提外对象的。所以,很多人会认为对象的传递是引用的传递而且很多人还可以举出以下的代码示例:

public static void main(String[] args) {
	JavaTest pt = new JavaTest( );
	
	User hollis = new User();
	hollis.setName("Hollis");
	hollis .setGender("Male");
	pt.pass(hollis);
	System.out.println("print in main , user is " + hollis);
}

public void pass(User user) {
	user.setName("hollischuang");
	System.out.println("print in pass , user is " + user);
}

输出结果:
print in pass , user is User{name=‘hollischuang’, gender=‘Male’}

print in main , user is User{name=‘hollischuang’, gender=‘Male’}

可以看到,对象类型在被传递到pass方法后,在方法内改变了其内容,最终调用方法main中的对象也变了。


所以,很多人说,这个和引用传递的现象是一样的,就是在方法内改变参数的值,会影响到调用方。但是,其实这是走进了一个误区。

一起来看一看

✅Java中的对象传递

很多人通过代码示例的现象说明Java对象是引用传递,那么我们就从现象入手,先来反驳下这个观点。

我们前面说过,无论是值传递,还是引用传递,只不过是求值策略的一种,那求值策略还有很多,比如前面提到的共享对象传递的现象和引用传递也是一样的。那凭什么就说Java中的参教传递就一定是引用传递而不是共享对象传递呢?

那么,Java中的对象传递,到底是哪种形式呢? 其实,还真的就是共享对象传递。

其实在《The Java™ Tutorials》中,是有关于这部分内容的说明的。首先是关于基本类型描述如下:

Primitive arguments, such as an int or a double, are passed into methods by value. This meansthat any changes to the values of the parameters exist only within the scope of the method.When the method returns, the parameters are gone and any changes to them are lost.

翻译过来即:原始参数通过值传递给方法。这意味着对参数值的任何更改都只存在于方法的范围内。当方法返回时,参数将消失,对它们的任何更改都将丢失。

关于对象传递的描述如下:

Reference data type parameters, such as objects, are also passed into methods by value. Thismeans that when the method returns, the passed-in reference still references the same object asbefore. However. the values of the obiect’ s fields can be chanaed in the method., if they have the proper access level.

即:引用数据类型参数(如对象)也按值传递给方法。这意味着,当方法返回时,传入的引用仍然引用与以前相同的对象。但是,如果对象字段具有适当的访问级别,则可以在方法中更改这些字段的值。

这一点官方文档已经很明确的指出了,Java就是值传递,只不过是把对象的引用当做值传递给方法。你细品,这不就是共享对象传递么?

其实Java中使用的求值策略就是传共享对象调用,也就是说,Java会将对象的地址的拷贝传递给被调函数的形式参数。只不过"传共享对象调用"这个词并不常用,所以ava社区的人通常说"Java是传值调用",这么说也没错,因为传共享对象调用其实是传值调用的一个特例。

✅值传递和共享对象传递的现象冲突吗?

看到这里很多人可能会有一个疑问,既然共享对象传递是值传递的一个特例,那么为什么他们的现象是完全不同的呢?

难道值传递过程中,如果在被调方法中改变了值,也有可能会对调用者有影响吗? 那到底什么时候会影响什么时候不会影响呢?

其实是不冲突的,之所以会有这种疑惑,是因为大家对于到底是什么是”改变值"有误解。

我们先回到上面的例子中来,看一下调用过程中实际上发生了什么?

在这里插入图片描述
在参数传递的过程中,实际参数的地址 X1213456 被拷贝给了形参。这个过程其实就是值传递,只不过传递的值得内容是对象的引用。


那为什么我们改了user中的属性的值,却对原来的user产生了影响呢?


其实,这个过程就好像是:你复制了一把你家里的钥匙给到你的朋友,他拿到钥匙以后,并没有在这把钥匙上做任何改动,而是通过钥匙打开了你家里的房门,进到屋里,把你家的电视给砸了。
这个过程,对你手里的钥匙来说,是没有影响的,但是你的钥匙对应的房子里面的内容却是被人改动了。

也就是说,Java对象的传递,是通过复制的方式把引用关系传递了,如果我们没有改引用关系,而是找到引用的地址,把里面的内容改了,是会对调用方有影响的,因为大家指向的是同一个共享对象。

那么我们来改动一下pass方法的内容:

public void pass(User user) {
	user = new User() ;
	user.setName("hollischuang");
	user.setGender("Male");
	System.out.println("print in pass , user is " + user);
}

上面代码中,我们在pass方法中,重新new了一个user对象,并改变了它的值,输出结果如下:

print in pass , user is User{name='hollischuang , gender=‘Male’}
print in main , user is User{name=‘Hollis’, gender=‘Male’}

再看一下整个过程发生了什么:

在这里插入图片描述

这个过程,就好像你复制了一把钥匙给到你的朋友,你的朋友拿到你给他的钥匙之后,找个锁匠把他修改了一下,他手里的那把钥匙变成了开他家锁的钥匙。这时候,他打开自己家,就算是把房子点了,对你手里的钥匙,和你家的房子来说都是没有任何影影响的。


所以,Java中的对象传递,如果是修改引用,是不会对原来的对象有任何影响的,但是如果直接修改共享对象的属性的值,是会对原来的对象有影响的

✅总结

    我们知道,编程语言中需要进行方法间的参数传递,这个传递的策略叫做求值策略。

    在程序设计中,求值策略有很多种,比较常见的就是值传递和引用传递。还有一种值传递的特例 —— 共享对象传递。

    值传递和引用传递最大的区别是传递的过程中有没有复制出一个副本来,如果是传递副本,那就是值传递,否则就是引用传递。

    在Java中,其实是通过值传递实现的参数传递,只不过对于Java对象的传递,传递的内容是对象的引用。

我们可以总结说,Java中的求值策略是共享对象传递,这是完全正确的。

但是,为了让大家都能理解你说的,我们说Java中只有值传递,只不过传递的内容是对象的引用。这也是没毛病的。

但是,绝对不能认为Java中有引用传递。

OK,以上就是本文的全部内容,不知道本文是否帮助你解开了你心中一直以来的疑惑。欢迎留言说一下你的想法。

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

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

相关文章

实现个人日志命令行工具(C语言)

〇、前言 中午上课的时候,打开 github 看了一下个人主页,虽然最近很忙,但是这个活动记录有点过于冷清: 于是我就想着写一个日志命令行工具,输入以下命令就能将我的日志立即同步到 github 上: mylog toda…

<软考>软件设计师-5计算机网络(总结)

1 网络功能和分类 1-1计算机网络的功能 计算机网络是计算机技术与通信技术相结合的产物,它实现了远程通信、远程信息处理和资源共享。计算机网络的功能:数据通信、资源共享、负载均衡、高可靠性。 1-2计算机网络按分布范围划分 1-3网络的拓扑结构 总线型&#xff0…

【论文笔记】动态蛇卷积(Dynamic Snake Convolution)

精确分割拓扑管状结构例如血管和道路,对医疗各个领域至关重要,可确保下游任务的准确性和效率。然而许多因素使分割任务变得复杂,包括细小脆弱的局部结构和复杂多变的全局形态。针对这个问题,作者提出了动态蛇卷积,该结…

iPhone手机开启地震预警功能

iPhone手机开启地震预警功能 地震预警告警开启方式 地震预警 版权:成都高新减灾研究所 告警开启方式

kali-捆绑应用程序

文章目录 一、安装开发环境二、开始捆绑三、开始监听 操作环境 kali windows 一、安装开发环境 ┌──(kali㉿kali)-[~] └─$ sudo -i [sudo] kali 的密码:┌──(root㉿kali)-[~] └─# whoami root┌──(root㉿kali)-[~] └─# apt update …

【设计模式--行为型--备忘录模式】

设计模式--行为型--备忘录模式 备忘录模式定义结构案例实现白箱备忘录模式黑箱备忘录模式 优缺点使用场景 备忘录模式 定义 又叫快照模式,在不破坏封装性的前提下,捕获一个对象的对象的内部状态,并在该对象之外保存这个状态,以便…

测试工具Jmeter:界面介绍、核心选项说明、核心选项用途

本文章主要介绍Jmeter的界面布局,以及各个选项的功能和它们的用途。 JMeter基本原理是建立一个线程池,多线程运行取样器产生大量负载,在运行过程中通过断言来验证结果的正确性,通过监听器来记录测试结果。 1. Jmeter主界面 当我…

银行测试:第三方支付平台业务流,功能/性能/安全测试方法

1、第三方支付平台的功能和结构特点 在信用方面,第三方支付平台作为中介,在网上交易的商家和消费者之间作一个信用的中转,通过改造支付流程来约束双方的行为,从而在一定程度上缓解彼此对双方信用的猜疑,增加对网上购物…

计算机组成原理(存储器的校验)

存储器的校验 说到存储器的校验就是海明码(汉明码),这种题型有两种: 1.编码问题:根据要传送的二进制代码来确定其对应的海明码(汉明码) 2.检错问题:已知收到的汉明码,…

在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装教程

在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装教程 VMware 虚拟机解锁 macOS 安装选项使用 macOS iso 系统镜像安装使用 OpenCore 做引导程序安装 在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装…

硬件产品经理:硬件产品敏捷开发

目录 简介 敏捷 CSDN学院 作者简介 简介 之所以敏捷产品开发流程会越来越普遍。 主要得益于这个方法可以让企业使用更少的资源去开发出令客户满意的新产品。 敏捷开发强调的最重要的一点就是“快”。 也就是要求通过快速迭代来获取频繁的客户反馈。 这就特别适合应对市…

腾讯云微服务11月产品月报 | TSE 云原生 API 网关支持 WAF 对象接入

2023年 11月动态 TSE 云原生 API 网关 1、支持使用私有 DNS 解析 服务来源支持私有 DNS 解析器,用户可以添加自己的 DNS 解析器地址进行私有域名解析,适用于服务配置了私有域名的用户。 2、支持 WAF 对象接入 云原生 API 网关对接 Web 安全防火墙&…

基于“Galera+MariaDB”搭建多主数据库集群的实例

1、什么是多主数据库集群 多主数据库集群是一种数据库集群架构,每个节点都可以接收写入操作和读取操作,并且通过心跳机制同步数据,保证数据一致性和高可用性。因多主数据库集群每个节点都可以承担读写操作,因此它可以充分利用各个…

【无语】Microsoft Edge 浏览器不显示后台返回的数值数据

Microsoft Edge 禁用 JSON 视图 写在前面禁用 JSON 视图 写在前面 遇到一个有意思的事情,在用 Microsoft Edge 浏览器发送请求测试时发现,后端返回的数值数据没有正常展示,而是类似查看源码的结果,只显示了一个行号1,…

java读取含有合并单元格的Excel

java读取含有合并单元格的Excel Excel如下: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.*;import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.…

redis 7.2.3 官方配置文件 redis.conf sentinel.conf

文章目录 Intro解压配置使用等官方配置文件模板redis.conf 仅配置项redis.conf 完整版(配置项注释)sentinel.conf 仅配置项sentinel.conf 完整版(配置项注释) Intro 在下载页面:https://redis.io/download/ 下载最新版本的redis: https://github.com/re…

线上环境如何正确配置 Django 的 DEBUG?

Author:rab Django Version:3.2 Python Version:3.9 目录 前言一、DEBUG True二、DEBUG False三、页面异常解决总结 前言 由于最近在学习 Django 的知识,于是尝试开发了一套 Blog 系统,在本地测试时是页面显示没问题…

STM32/STM8资源节约主义编程方式

STM32/STM8资源节约主义编程方式 在小资源芯片进行代码设计时,如STM32C0系列,STM8系列,因为官方库本身要包含各种场景应用特征的支持,所以会有一些冗余的代码占用更多FLASH空间。当需要实现资源占用最简化设计方式时,…

Java实现一个在windows环境下的文件搜索引擎

以下是一个简单的Java实现的Windows文件搜索引擎的示例代码: import java.io.File; import java.util.ArrayList; import java.util.List;public class FileSearchEngine {public static void main(String[] args) {String searchDirectory "C:/"; // …

在WPF窗口中增加水印效果

** 原理: ** 以Canvas作为水印显示载体,在Canvas中创建若干个TextBlock控件用来显示水印文案,如下图所示 然后以每一个TextBlock的左上角为中心旋转-30,最终效果会是如图红线所示: 为了达到第一行旋转后刚好与窗口…