Java中为什么只有值传递?

Java中为什么只有值传递?

对于对象参数而言,实际参数传递给形式参数的只是一个内存地址,让形式参数也指向实际参数所指向的地址,传递的值的内容是对象的引用。

为什么会是这样?让我慢慢为你讲解。

对于Java的传递类型,常见错误理解如下:

错误理解一:值传递和引用传递,区分的是传递内容;如何是值,就是值传递;如果是引用,就是引用传递;

错误理解二:Java是引用传递;

错误理解三:传递的参数如果是普通类型,那就是值传递;如果是对象,那就是引用传递。

我们都知道,Java中定义方法的时候是可以定义参数的,比如Java中的main方法,方法中的args就是参数。

public static void main(String[] args)

参数在程序语言中分为实际参数和形式参数。

实际参数由主调函数传入,被调函数接受由主调函数传入的参数(也称为形式参数)。

当我们在程序中调用一个有参函数时,会将实际参数传递给形式参数。这个传递过程分为:值传递和引用传递。

值传递:调用函数传递实际参数时,会将实际参数复制一份副本,将复制的副本传入形式参数,当函数对参数进行修改时,修改的只是副本参数,不会影响到实际参数。

引用传递:调用函数传递实际参数时,会将实际参数的地址传递到形式参数,当函数对参数进行修改时,会影响到实际参数。

值传递

引用传递

区别

创建副本传入传入

将对象地址传入

结果

函数中无法修改原始变量

函数中能够修改原始变量

在了解上述概念后,可以写一段代码验证一下,看看Java中到底是值传递?还是引用传递?

在pass方法中修改参数j的值,分别打印出main方法和pass方法中的j值,看看输出结果有什么变化;

最终结果是,pass方法中修改的j值,并没有影响到main方法中的j值。

在接着看如下代码:

在pass方法中修改User对象的值,看看输出结果值:

这次实参的值居然被改变了,根据上述引用传递的定义,实际参数被修改了,这不就是引用传递吗?

先不要着急下结论,在看一个参数类型为对象的参数传递:

输出结果

这又是怎么回事呢?同样传递了一个对象,实际参数却没有被修改,又变成了值传递了?

这里先说一下String类型,当对String类型做任何修改时,都会产生新的String,值也是会变的。

上述的三个例子,表现结果却不一样,这就导致初学者出现困惑,甚至很多高级程序员对值传递都会存在困惑。

再举一个比较形象的例子,在深入理解一下值传递和引用传递

你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。
你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了。那你说你会不会受到影响?而我们在pass方法中,改变user对象的name属性的值的时候,不就是在“砸电视”么。你改变的不是那把钥匙,而是钥匙打开的房子。

在拿上面的一个例子进行举例,真正的改变参数,看看会发生什么变化?

输出结果

通过一张图,你就能理解整个过程发生了什么,然后在告诉你,Java中为什么只有值传递?

当在main方法中创建一个User对象时,编译器会在堆中开辟一块内存,保存对象中name和gender的值,然后对象hollis指向该内存的对象0X1234456,如上图所示。

在调用pass方法时,hollis作为实际参数传入到形式参数user,会一并将地址0X123456传递给user,使user也指向地址0X123456,如上图所示。

在pass方法中对参数user进行修改,即重新实例化user,此时user会重新开辟一块内存地址0X45678,使user指向该地址,后面对user的任何修改,都不会在改变地址0X123456中的值,如上图所示。

看到这里,你觉得上述示例是什么传递方式?那肯定不是引用传递,如果是引用传递,肯定会修改实际参数的值,而实际上并没有修改实际参数的值。

这时你在返回去理解一下值传递和引用传递的概念,你就会发现上述的例子实际上是将实际参数的地址传递给了形式参数。

所以上面的传递方式是值传递,并非引用传递,把实际参数的地址当作值传递给形式参数。

在来回顾下这个例子:

看看这个例子中的传递过程发生了哪些变化?

在参数传递过程中,只是把实际参数的地址0X123456传递给了形式参数,方法中没有对形参本身进行修改,而只是修改形参指向地址中的值。

所以,值传递和引用传递的区别并不是在于传递的内容,而是实参到底有没有被复制一份给形参。

在判断实参内容有没有受到影响的时候,要看传递的内容是什么?如果你传递的是地址,就要注意这个地址的变化会不会有影响,而不是看地址指向对象的变化。

讲到这里,我们在反过头来看看String对象,同样都是传递对象,为什么String和User的表现结果不一样呢?

在pass方法中使用name = "hollischuang"试着去更改实际参数name的值,结果直接改变了name的引用地址。

这是因为name = "hollischuang"这段代码,会new一个String对象,再让name指向这个新的地址,等价于下面这段代码:

name = new String("hollischuang");

而实参name还是指向“Hollis”字符串所在的地址,当pass中修改name对象时,并不会修改到实际参数name的值。

所以,这就是为什么Java中只有值传递?只不过对于对象参数,值的内容是对象的引用。

总结

无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy)。在求值策略中,还有一种叫做按共享传递(call by sharing)。其实Java中的参数传递严格意义上说应该是按共享传递。

按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值)。

在函数内部对参数进行操作时,需要先拷贝出地址,寻找到具体的值,再进行操作。如果该值在栈中,因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响。

如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作。因为传递的是地址的拷贝,所以函数内对值的操作对外部变量是可见的。

简单点说,Java中的传递,是值传递,而这个值,实际上是对象的引用。

而按共享传递其实只是按值传递的一个特例罢了。所以我们可以说Java的传递是按共享传递,或者说Java中的传递是值传递。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

引领国产洗碗机全面反超,是时候重新认识方太了

文 | 智能相对论 作者 | 佘凯文 2024AWE如期而至,方太作为全球领先的高端厨电专业制造商与创新引领者参与其中,并在开幕当天召开了以“Hi-tech,Hi life”为主题的2024春季新品发布会。 发布会上,方太公布了由国家工业信息安全发…

实验室管理系统 |基于springboot框架+ Mysql+JSP技术+Tomcat的实验室管理系统 设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 用户后台功能模块 用户后台管理 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunw…

【01】htmlcssgit

01-前端干货-html&css 防脱发神器 一图胜千言 使用border-box控制尺寸更加直观,因此,很多网站都会加入下面的代码 * {margin: 0;padding: 0;box-sizing: border-box; }颜色的 alpha 通道 颜色的 alpha 通道标识了色彩的透明度,它是一个 0~1 之间的取值,0 标识完全…

创业新手看过来!四招助你开启成功之旅

如果你每个月的薪资仅有几千块,还背负着债务的重担,家中的老少都期盼着你为他们撑起一片天,那么,你每日都可能为了如何打破这一困境而焦虑不安。不过,请稍安勿躁,今天我将为你提供四个建议,或许…

【C语言】浮点型在内存中的存储

文章目录 例题引入剖析原因浮点型的二进制转换(M)正负号之分(S)科学记数法(E)关于 S E M 在内存中的存储存取浮点型时的情况讨论 例题解析整形存储为浮点型并输出浮点型存储为整形并输出 在我的上一篇博客中…

[De1CTF 2019]SSRF Me ---不会编程的崽

这个题更偏向于代码审计。耐住性子慢慢理解,还是挺简单的。 很直接哦,就给源码。这么看不好看,得去pycharm里修正一下格式 #放在pycharm里CtrlAltL将代码格式化一下 1 #! /usr/bin/env python2 #encodingutf-83 from flask import Flask4 fr…

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列?二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机(Virtual Host)3.2.2、交换机(Exchange)3.2.2…

2024年【电工(初级)】考试资料及电工(初级)实操考试视频

题库来源:安全生产模拟考试一点通公众号小程序 电工(初级)考试资料根据新电工(初级)考试大纲要求,安全生产模拟考试一点通将电工(初级)模拟考试试题进行汇编,组成一套电…

springboot项目学习-瑞吉外卖(1)

第一天任务如下: 建立基本架构完成登录、退出功能 注意:本博客没有使用网上教程里的mybatis-plus,使用的是mybatis;数据库连接池也没有使用教程里的druid,使用的是spring自带的连接池 基本架构 common包:存…

【代码】求出指定图片的平均RGB颜色值

import cv2求出指定图片的平均颜色值# 读取图片 image cv2.imread(D:\\Desktop\\0001.png)# 计算平均颜色 # cv2.mean()函数会返回图像所有通道的平均值 # 这里的平均值是按通道分别计算的,返回值是一个包含每个通道平均值的元组 average_color_per_channel cv2.m…

Radware DDoS防护迎来重大升级,重拳出击在线游戏行业难题

日前,全球领先的网络安全和应用交付解决方案提供商Radware推出了多维DDoS检测和防护措施,以满足在线游戏行业独特复杂的需求。Radware开发了一系列新的算法来保护在线游戏免遭复杂攻击。 Radware首席运营官Gabi Malka表示:“在线游戏是价值数…

掘根宝典之c++有符号(signed)和无符号类型(unsigned)

在c中,有符号和无符号是针对整型而言的 在C中,除了布尔类型和拓展的字符类型之外,其他整型可以划分为有符号类型(signed)和无符号类型(unsigned),用于表示整数。 有符号类型可以表…

外卖点餐系统 |基于springboot框架+ Mysql+Java+JSP技术+Tomcat的外卖点餐系统 设计与实现(可运行源码+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 骑手功能模块 商家功能模块 管理员功能登录前台功能效果图 用户功能模块 系统功能设…

Linux网络编程: 以太网帧Frame/ARP/RARP详解

一、TCP/IP五层模型 物理层(Physical Layer):物理层是最底层,负责传输比特流(bitstream)以及物理介质的传输方式。它定义了如何在物理媒介上传输原始的比特流,例如通过电缆、光纤或无线传输等。…

【AcWing】蓝桥杯集训每日一题Day5|归并排序|离散化|二分|逆序数对|505.火柴排队(C++)

火柴排队 505. 火柴排队 - AcWing题库难度:中等时/空限制:1s / 128MB总通过数:2058总尝试数:4484来源:NOIP2013提高组算法标签贪心离散化树状数组归并排序 题目内容 涵涵有两盒火柴,每盒装有 n 根火柴…

04-java基础--流程控制语句

一、switch语句 二、循环的三种结构 流程控制语句分为三种结构: 顺序结构(按代码的书写顺序执行,从上到下依次执行)分支结构(if语句、if–else语句、switch语句)循环结构(while、for循环、do–…

Guitar Pro8许可证2024最新免费

作为一位吉他爱好者推荐官,我非常荣幸地向大家介绍一款备受赞誉的吉他工具——Guitar Pro8。这款软件是吉他爱好者们的必备之选,它以其卓越的功能和优势,全面覆盖学习演奏和绘谱创作的需求,帮助吉他爱好者们更好地提升自己的技能。…

数据预处理|数据清洗|使用Pandas进行异常值清洗

数据预处理|数据清洗|使用Pandas进行异常值清洗 使用Pandas进行异常值清洗1. 异常值检测1.1 简单统计分析1.2 散点图方法1.3 3σ原则1.4 箱线图 2. 异常值处理2.1 直接删除2.2 视为缺失值2.3 平均值修正2.4 盖帽法2.5 分箱平滑法2.6 回归插补2.7 多重插补2.8 不处理 使用Pandas…

creator-webview加载优化

title: creator-webview加载优化 categories: Cocos2dx tags: [cocos2dx, creator, webview, 优化, 加载, 性能] date: 2024-03-02 13:17:20 comments: false mathjax: true toc: true creator-webview加载优化 前篇 Android WebView shouldInterceptRequest - https://www.ji…

Java微服务 第二十一章 Java多线程安全与锁

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 往期热门专栏回顾 专栏描述Java项目实战介绍Java组件安装、使用;手写框架等Aws服务器实战Aws Linux服务器上操作…